Asp.net Usercontrol LoadControl问题

时间:2008-10-27 17:58:29

标签: asp.net user-controls loadcontrol

使用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应用程序的其他地方,我使用以下代码向页面添加了一个usercontrol实例:

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

我正在使用LoadControl的重载版本,因为我想将Message参数传递给构造函数。所有这些出现才能正常工作。

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

任何人都可以解释为什么会发生这种情况吗?

由于

修改

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

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

6 个答案:

答案 0 :(得分:21)

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

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 :(得分:0)

同意Mitchel,你应该能够在控制代码本身中放置一个page_load,它将在控件完全可用后触发。

答案 2 :(得分:0)

总是添加你自己的load事件并在你运行构造函数并将控件添加到页面之后调用它,但它与你拥有的并没有很大不同,尽管我可能会因为样式原因而选择它。 / p>

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

答案 3 :(得分:0)

Here是由Steven Robbins撰写的博客文章。该帖子解释了如何使用LoadControl传递用户控件的参数,类似于LoadControl(Type, object[])将执行的操作,除了工作:)

答案 4 :(得分:0)

我在Calendar控件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标记

     

表单上的Calendar 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

答案 5 :(得分:-1)

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