【问题标题】:All controls are null within usercontrol用户控件中的所有控件都为空
【发布时间】:2011-11-16 23:40:52
【问题描述】:

我有一个使用 UserControl 以及其他控件的 UserControl。

ascx 文件中,我有以下代码:

<%@ Register TagPrefix="tag" Namespace="some.name.space" Assembly="some.assembly" %>
<tag:control ID="test" runat="server" />

在我的Page_Load 方法中,我尝试在测试中设置一个属性,如下所示:

test.Text = "Hello World!";

这实际上在我的用户控件test 中设置了文本控件的文本属性。

这会引发异常:

对象引用未设置为对象的实例

当它试图设置

lblTest.Text = value; 

为空的对象是lblTest

我没有正确添加用户控件吗?我应该 - 还是必须 - 在注册标签时指定 Src 属性?如果是这样,我必须注册我使用的每个用户控件?

这也导致用户控件中没有控件加载,并且用户控件中的所有控件都为空。

【问题讨论】:

    标签: c# asp.net .net user-controls


    【解决方案1】:

    如果用户控件在您当前的项目中,那么您需要在 register 语句中包含 src:

    <%@ Register TagPrefix="uc1" TagName="NavTop" Src="controls/NavTop.ascx" %>
    

    但是,如果你在多个页面中使用这个用户控件,那么你也可以在 web.config 中注册它:

    <system.web>
      <pages>
        <controls>
          <add tagPrefix="uc1" tagName="NavTop" src="~/controls/NavTop.ascx" />
        </controls>
      </pages>
    </system.web>
    

    另一件需要注意的事情:如果您只在源视图中进行更改,则有时 Visual Studio 设计人员不会“看到”您对页面上的控件所做的更改。例如,如果您更改控件名称,您最终可能会在 ascx 中使用新名称的控件,但在设计器文件中会引用具有旧名称的控件。在运行时,这将导致设计器文件属性为空。

    在多次被此烧毁后,如果我在源视图中进行任何更改,我要么检查设计器文件是否已正确更新,要么切换到设计视图,进行微小更改,然后保存页面/用户控件。

    【讨论】:

    • 谢谢@competent_tech 关于在web.config 中注册控件我注意到的一点是,如果控件是同一目录中控件的复合控件 - 将会出现错误。如果有人可以向我解释,我很想知道为什么会这样。
    【解决方案2】:

    当我以错误的方式在代码中添加用户控件时,我遇到了这个问题。你必须使用 Page.LoadControl 方法来初始化你不能只使用 new 的控件。

            //WRONG
            UserControls.BingoCardPage bcp = new UserControls.BingoCardPage();
            form1.Controls.Add(bcp);
            //RIGHT
            UserControls.BingoCardPage bcp = (UserControls.BingoCardPage)Page.LoadControl("~/UserControls/BingoCardPage.ascx");
            form1.Controls.Add(bcp);
    

    【讨论】:

    • 这对我有用。我已经通过 web.config 添加了控件,但就我而言,这还不够。
    【解决方案3】:

    这里的问题通常是由于用户控件的加载机制,它们通常在页面之后加载。因此,在包含 page_load 方法期间,控件尚未在您的用户控件上初始化(导致 null ref)。解决此问题的一种方法是在用户控件上创建和设置一个属性,并让用户控件在其 Page_Load 方法中连接/填充其自己的 UI。

    类似这样的:

    //Page
    protected void Page_Load(object sender, EventArgs e)
    {
        test.Text = "Hello World!";
    }
    
    //User Control
    public string Text {get; set;}
    
    protected void Page_Load(object sender, EventArgs e)
    {
        lblTest.Text = Text;
    }
    

    【讨论】:

      【解决方案4】:

      请尝试将代码放入页面的Page_prerender 事件中。它会为你工作。

      【讨论】:

      • 使用 PreRender 填充控件的问题是,如果控件上有任何与其他控件交互的事件,除非在加载期间填充,否则数据将丢失。如果您在加载期间填充控件,您将在 preRender 期间访问该数据。加载 -> 事件触发 -> 预渲染。当您想确保数据不会过时(可能被事件更改)时,应该使用 PreRender。
      • 请注意,Page.PreRender 发生在 page.Load 之后,页面上的任何控件触发其 Load 事件......在 Page 实际呈现之前。这是将数据绑定到控件的最后机会。
      猜你喜欢
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多