在Page_Load期间,设计器中添加的控件为null

时间:2010-03-24 17:33:38

标签: c# asp.net user-controls

以下所有名称都是通用的,而不是实际使用的名称。

我有一个自定义的UserControl,其Panel包含一些标签,两个.aspx控件。

的.aspx:

<asp:Panel runat="server">
    <asp:Label ID="label1" runat="server">
    </asp:Label>
</asp:Panel>
<asp:Panel runat="server">
    <asp:Label ID="label2" runat="server">
    </asp:Label>
</asp:Panel>

代码隐藏:

private readonly Object object;
protected void Page_Load(object sender, EventArgs e)
{
    // These are the lines that are failing
    // label1 and label2 are null
    label1.Text = object.Value1;
    label2.Text = object.Value2;
}
public ObjectRow(Object objectToDisplay)
{
    object = objectToDisplay;
}

在另一个页面上,在后面的代码中,我创建了一个自定义用户控件的新实例。

protected void Page_Load(object sender, EventArgs e)
{
    Usercontrol control = new UserControl(object);
    Controls.Add(control);
}

用户控件接受参数并尝试根据传入的对象设置标签。

但是,它尝试将值分配给的标签为null。

这是一个我不理解的ASP.net生命周期问题吗?我基于Microsoft ASP.net lifecycle page的理解是页面控件在Page_Initialization之后可用。

这样做的正确方法是什么?还有更好的方法吗?

编辑:从下面我尝试过使用Page.LoadControl。

如果我根据路径和文件名的字符串表示加载控件,则禁止传递参数。我可以通过添加允许我设置对象的方法来避免这种情况。这虽然有效,但感觉很乱。如果可能的话,我希望能够将值传递给构造函数。

使用重载方法会产生与仅加载后面的代码相同的结果,正在分配的标签为空。

编辑:显然,重载方法没有实例化.ascx文件中添加的子控件是“按设计”。我在Microsoft's page for Page.LoadControl(type, object[])

的评论中找到了这个

3 个答案:

答案 0 :(得分:11)

当您在用户控件的类后面创建代码实例时,不会创建用户控件的实例。实际的用户控件是从.ascx文件中的标记创建的类,该类继承自类后面的代码。

如果要动态创建用户控件,请使用Page.LoadControl方法。它将创建一个用户控件的实例,其中控件引用后面的代码对应于从标记创建的控件:

CustomControl control = (CustomControl)Page.LoadControl("controls/CustomControl.ascx");

但是这并没有让你有机会将参数发送给构造函数,所以你可能想要使用带有类型的重载:

CustomControl control = (CustomControl)Page.LoadControl(typeof(CustomControl), new object[] { objectToDisplay } );

(我不确定类型参数应该是什么。逻辑上它应该是.ascx页面的类型而不是类后面的代码类型。)

答案 1 :(得分:10)

在页面/父用户控件的标记中使用Register指令:

<%@ Register TagPrefix="wb" src="~/CustomControl.ascx" TagName="CustomControl" %>

<asp:CustomControl runat="server" />

答案 2 :(得分:0)

您可以尝试在自定义控件的Page_Load处理程序中调用EnsureChildControls,尽管AFAIK不是绝对必要的。

何时/何处将自定义控件添加到Controls集合?