2008-10-27 107 views
15

我使用LoadControl(type, Params)时,有一个问题。让我来解释......Asp.net用户控件LoadControl问题

我有一个超级简单的用户控件(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 usercontrol上触发OnPreRender()时,lblTitle和lblDescription变量均为null,尽管它们具有等价的标记。消息变量已正确填充。

任何人都可以阐明为什么这可能会发生任何轻?

感谢

编辑:

只是为了清楚起见,我还要补充一点,这是编程添加用户控件的页面的代码响应按钮按下时运行,所以“托管页面“已经通过Init,Page_Load进行并且正在处理事件处理程序。

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

回答

19

我曾尝试下面的代码,以及 - 这将产生相同的结果(即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 initalise控制?

编辑:

好了,我回答我的问题在这里..

我发现论坛后我联系到上述Here

本质答案的回答版本是LoadControl(type, params)无法推断'页面infront'ascx解析,因此它并没有扰乱任何控制。当你使用LoadControl("ascx path")版本时,它被赋予页面infront,因此完成所有的解析和initalision。

所以总而言之,我需要改变这个代码,这个代码是将控件初始化并将它分成单独的部分。即

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

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

我仍然愿意提出改进上述建议。

干杯

+3

+1和我的谢谢你解决我遇到的问题。 :) – 2008-12-27 12:06:09

-1

%的asp.net页面生命周期的控制并没有完全在预渲染,你为什么不只是加载值加在Page_Load中?

+1

上这是不正确的。 [PreRender在加载后发生](http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events)`在页面对象创建所有控件后引发' – Chris 2011-05-24 00:26:09

0

与米切尔达成一致,你应该能够把Page_Load中的控制代码本身的控制是完全可以后这将触发。

+1

[PreRender在*加载后发生] (http://msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events),所以PreRender应该是安全的。 – Chris 2011-05-24 00:27:53

0

嘛总是有添加自己的加载事件,并调用它,你已经跑构造并添加控件到页面后,但它并不比你有什么不同了很多,虽然我可能会选择它出于风格的原因。

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

0

Here是由史蒂芬罗宾斯写的博客文章。帖子介绍了如何传递参数使用LoadControl,类似于LoadControl(Type, object[])会做一个用户控件,除了它的工作原理 :)

0

我曾与Calendar控件的DayRender事件类似的问题,我想补充e.Cell.Controls集合的用户控件。在用户控件page_load没有触发或者ascx上的列表框没有引发null异常的情况下尝试了一些失败的方法后,我发现如果我使用LoadControl(ascx)初始化表单上的控件,然后开始访问标记控件ascx,一切正常。这种方法根本不依赖于ascx上的Page_Load事件。

ASCX标记

背后

公共类CPCalendarCell 继承System.Web.UI程序代码。背后日历的DayRender事件用户控件

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标记

代码的形式

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