简体   繁体   English

将用户控件动态添加到页面会使 UC 内的控件为空

[英]Dynamically adding a usercontrol to a page leaves controls inside the UC to null

I need to add a UserControl dynamicaaly to a Panel on a page.我需要将 UserControl dynamicaaly 添加到页面上的面板。 The UserControl has a Repeater with the ID of ARepeater. UserControl 有一个Repeater,ID 为ARepeater。 I load and add the UC on Page_Init.我在 Page_Init 上加载并添加了 UC。 I examine the value of ARepeater in Init, Load, and PreRender events of UC but ARepeater is always null.我在 UC 的 Init、Load 和 PreRender 事件中检查了 ARepeater 的值,但 ARepeater 始终为空。

protected Page_Init(object sender, EventArgs e)
{
  var list = (NameList)Page.LoadControl(typeof(NameList), new object[1] { (int)Type });
  Panel1.Controls.Add(list);
}

The NameList.ascx NameList.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="NameList.ascx.cs" Inherits="MyCompant.Controls.BannersList" %>
   <asp:Repeater ID="ARepeater" runat="server">
      <ItemTemplate>
      </ItemTemplate>
    </asp:Repeater>

What I am doing wrong?我做错了什么?

First of all, you do not need to be in Page_Init to work with dynamic controls.首先,您不需要在Page_Init中使用动态控件。 Page_Load is just fine. Page_Load就好了。 But in order to fill the Repeater you can create a property in the UserControl但是为了填充中继器,您可以在 UserControl 中创建一个属性

public partial class WebUserControl1 : System.Web.UI.UserControl
{
    public Repeater _ARepeater
    {
        get
        {
            return ARepeater;
        }
        set
        {
            ARepeater = value;
        }
    }


    protected void Page_Load(object sender, EventArgs e)
    {
    }

Then you can access it from the page using the UserControl.然后您可以使用 UserControl 从页面访问它。

protected void Page_Load(object sender, EventArgs e)
{
    var list = (WebUserControl1)LoadControl("~/WebUserControl1.ascx");
    list.ID = "MyUserControl";
    Panel1.Controls.Add(list);

    list._ARepeater.DataSource = source;
    list._ARepeater.DataBind();
}

Or use FindControl或者使用 FindControl

var _ARepeater = (Repeater)Panel1.FindControl("MyUserControl").FindControl("ARepeater");
_ARepeater.DataSource = dt;
_ARepeater.DataBind();

You probably won't like this answer, but the overload for Page.LoadControl that allows for specifying the control's type and adding constructor arguments doesn't bind the ascx to the code-behind, and all associated child-controls will end up being null.您可能不会喜欢这个答案,但是允许指定控件类型和添加构造函数参数的Page.LoadControl重载不会将ascx绑定到代码隐藏,并且所有关联的子控件最终都将为空.

In the past, I've worked around this by adding another method for setting dependencies after constructing the user control, but it's not an ideal solution.过去,我通过在构造用户控件后添加另一种设置依赖项的方法来解决此问题,但这不是理想的解决方案。

That said you aren't doing anything wrong.那就是说你没有做错任何事。 Binding will work properly if you use Page.LoadControl("~/path/to/mycontrol.ascx") , but you won't have constructor injection.如果您使用Page.LoadControl("~/path/to/mycontrol.ascx")绑定将正常工作,但您不会有构造函数注入。

I believe the issue lies with the fact that the backing class doesn't actually have a relationship with the front-end page, except through the page directive that specifies it as the code-behind class.认为问题在于支持类实际上与前端页面没有关系,除非通过页面指令将其指定为代码隐藏类。 Nothing stops multiple different front-ends using the same class as it's code-behind, so loading by Type makes it either very difficult or outright impossible to determine what the correct ascx to bind would be.没有什么可以阻止多个不同的前端使用相同的类,因为它是代码隐藏的,因此按Type加载使得确定要绑定的正确ascx非常困难或完全不可能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM