【问题标题】:Asp.net Usercontrol LoadControl IssueAsp.net 用户控制负载控制问题
【发布时间】:2008-10-27 17:58:28
【问题描述】:

我在使用 LoadControl( type, Params ) 时遇到问题。让我解释一下……

我有一个超级简单的用户控件(ascx)

<%@ Control Language="C#" AutoEventWireup="True" Inherits="ErrorDisplay" Codebehind="ErrorDisplay.ascx.cs" EnableViewState="false" %>

<asp:Label runat="server" ID="lblTitle" />
<asp:Label runat="server" ID="lblDescription" />

后面有代码(c#):

public partial class ErrorDisplay : System.Web.UI.UserControl
{

    private Message _ErrorMessage;    

    public ErrorDisplay()
    {
    }

    public ErrorDisplay(Message ErrorMessage)
    {
        _ErrorMessage = ErrorMessage;
    }    

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (_ErrorMessage != null)
        {
            lblTitle.Text = _ErrorMessage.Message;
            lblDescription.Text = _ErrorMessage.Description;
        }
    }
}

在我的 Web 应用程序的其他地方,我使用以下代码将用户控件的实例添加到页面:

divValidationIssues.Controls.Add(LoadControl(typeof(ErrorDisplay), new object[] { MessageDetails }));   

我正在使用 LoadControl 的重载版本,因为我想将 Message 参数传递给构造函数。所有这些似乎都可以正常工作。

但是,当在 ErrorDisplay 用户控件上触发 OnPreRender() 时,lblTitle 和 lblDescription 变量都是 null,尽管它们具有等效的标记。消息变量已正确填充。

谁能解释为什么会发生这种情况?

谢谢

编辑:

为了清楚起见,我还将添加以编程方式将用户控件添加到页面的代码正在运行以响应按钮按下,因此“托管页面”已通过 Init、Page_Load 进行,现在正在处理事件处理程序。

我无法在较早的 asp 生命周期阶段添加用户控件,因为它们是为响应按钮单击事件而创建的。

【问题讨论】:

    标签: asp.net user-controls loadcontrol


    【解决方案1】:

    我也尝试了以下代码 - 产生相同的结果(即 lblTitle 和 lblDescription 均为空)

    protected void Page_Load(object sender, EventArgs e)
    {
        if (_ErrorMessage != null)
        {
            lblTitle.Text = _ErrorMessage.Message;
            lblDescription.Text = _ErrorMessage.Description;
        }
    }
    

    我了解到,LoadControl 函数将它正在加载的控件带到包含它的页面的当前“状态”。因此 Init、Page_Load 等都作为 LoadControl 调用的一部分运行。

    有趣的是,这个(未答复的)asp.net 论坛帖子与我遇到的问题相同。

    MSDN Forums Post

    另外 - 来自 MSDN:

    当您将控件加载到容器控件中时,容器会引发所有已添加控件的事件,直到它赶上当前事件为止。但是,添加的控件无法赶上回发数据处理。要使添加的控件参与回发数据处理(包括验证),必须将控件添加到 Init 事件而不是 Load 事件中。

    因此 LoadControl 不应该正确初始化控件吗?

    编辑:

    好的,所以我在这里回答我自己的问题..

    我找到了上面链接到的论坛帖子的回复版本Here

    基本上答案是LoadControl( type, params ) 无法推断“页面前面” ascx 进行解析,因此它不会打扰初始化任何控件。当您使用 LoadControl( "ascx path" ) 版本时,它会在前面给出页面,因此会执行所有解析和初始化。

    总而言之,我需要更改初始化控件的代码并将其拆分为单独的部分。即

    Control ErrorCntrl = LoadControl("ErrorDisplay.ascx");
    ErrorCntrl.ID = SomeID;
    (ErrorCntrl as ErrorDisplay).SetErrorMessage = MessageDetail;
    divErrorContainer.Controls.Add(ErrorCntrl);
    

    它应该可以正常工作。它不像我之前的尝试那样整洁,但至少它会工作。

    我仍然愿意接受改进上述内容的建议。

    干杯

    【讨论】:

    • +1 和一封感谢信,感谢我解决了我遇到的问题。 :)
    【解决方案2】:

    同意 Mitchel 的观点,您应该能够在控件代码本身中放置一个 page_load,它会在控件完全可用后触发。

    【讨论】:

    【解决方案3】:

    好吧,在你运行构造函数并将控件添加到页面后,总会添加你自己的加载事件并调用它,但它与你所拥有的并没有太大的不同,尽管我可能会出于风格原因选择它。

    很高兴您找到了问题的答案!

    【讨论】:

      【解决方案4】:

      Here 是 Steven Robbins 撰写的博客文章。该帖子解释了如何使用LoadControl 为用户控件传递参数,类似于LoadControl(Type, object[]) 所做的,除了它有效 :)

      【讨论】:

        【解决方案5】:

        我在日历控件 DayRender 事件中遇到了类似的问题,因为我想向 e.Cell.Controls 集合添加一个用户控件。在尝试了几种失败的方法后,用户控件 page_load 未触发或 ascx 上的列表框抛出空异常,我发现如果我使用 LoadControl(ascx) 初始化表单上的控件,然后开始访问标记控件上ascx,一切正常。这种方法根本不依赖 ascx 上的 Page_Load 事件。

        ASCX 标记

        后面的代码

        公共类 CPCalendarCell 继承 System.Web.UI.UserControl

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        
        End Sub
        
        Public Sub Add(txt As String)
            Dim li As New ListItem(txt, txt)
            lstDay.Items.Add(li)
        End Sub
        

        结束类

        页面 ASPX 标记

        表单上的日历 DayRender 事件背后的代码

        Private Sub Calendar1_DayRender(sender As Object, e As System.Web.UI.WebControls.DayRenderEventArgs) Handles Calendar1.DayRender
            Dim div As CPCalendarCell = LoadControl("~/UserControls/CPCalendarCell.ascx")
            div.ID = "dv_" & e.Day.Date.ToShortDateString.Replace(" ", "_")
        
            **e.Cell.Controls.Add(div)**
        
            div.Add(e.Day.Date.Month.ToString & "/" & e.Day.Date.Day.ToString)
            div.Add("Item 1")
            div.Add("Item 2")
            e.Cell.Style.Add("background-color", IIf(e.Day.IsWeekend, "whitesmoke", "white").ToString)
        End Sub
        

        【讨论】:

          【解决方案6】:

          根据 asp.net 页面生命周期,您的控件并未完全添加到预渲染中,为什么不直接加载 page_load 中的值?

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-18
          相关资源
          最近更新 更多