用户控件内的所有控件均为空

23

我有一个使用了另一个用户控件以及其他控件的用户控件。

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


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

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

在我的Page_Load方法中,我尝试像这样设置test上的属性:


test.Text = "Hello World!";

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

这会抛出一个异常:

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

当它尝试设置时。

lblTest.Text = value; 

该为空的对象是 lblTest

我是否没有正确添加用户控件?我是否需要在注册标记时指定 Src 属性?如果是这样,我将不得不为使用的每个用户控件进行注册吗?

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

4个回答

29

如果用户控件在当前项目中,那么你需要在注册语句中包含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>

还有一件事情需要注意:在页面源代码中修改控件时,有时可视化工具无法“看到”您所做的更改。例如,如果您更改了控件名称,则.ascx文件中可能会出现一个使用新名称的控件,但设计文件中仍然引用旧名称的控件。在运行时,这将导致设计文件属性为空。

因为多次遭遇此类问题后,如果我在源代码视图中进行任何更改,我都会检查设计文件是否正确更新或者切换到设计视图,进行微小的更改,然后保存页面/用户控件。


1
感谢 @competent_tech。我注意到在 web.config 中注册控件的一件事情是,如果一个控件是同一目录中的控件组合控件,则会出现错误。如果有人能解释一下这是为什么,我很想知道。 - VFein

8

当我在错误的方式下向代码后端添加用户控件时,遇到了这个问题。您必须使用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);

1
这对我有用。我已经通过web.config添加了控件,但在我的情况下仅仅添加控件是不够的。 - Adrian K

5
通常情况下,这里的问题是由于用户控件的加载机制,它们通常在页面之后加载。因此,在包含页面中的page_load方法期间,您的用户控件上的控件尚未初始化(导致空引用异常)。一个解决方法是在用户控件上创建并设置属性,并让用户控件在其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;
}

1
请尝试将代码放置在页面的Page_prerender事件中。这样做对您有帮助。

使用PreRender填充控件的问题在于,如果控件上有任何与其他控件交互的事件,除非在加载期间填充,否则数据将丢失。如果您在加载期间填充控件,则可以在preRender期间访问该数据。加载->事件触发->PreRender。当您想确保数据不陈旧(可能会被事件更改)时,应该使用PreRender。 - Gary.S
请注意,Page.PreRender事件发生在页面加载(page.Load)以及任何控件触发其Load事件之后...在页面实际渲染之前。这是将数据绑定到控件的最后机会。 - Bruce Allen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接