【问题标题】:Nested ASP.NET user control is null嵌套的 ASP.NET 用户控件为空
【发布时间】:2023-04-02 21:25:02
【问题描述】:

我正在使用 Visual Studio 2017 和 .NET 4.7.1 开发一个 ASP.NET 应用程序。我有一个简单的用户控件,名为ContentStatsViewer.ascx,它显示了几个标签。要显示的值通过公共属性传递。

NumericContentStatsViewer.ascx 等其他控件包括ContentStatsViewer.ascx 的实例以及其他内容,如下所示:

<uc:ContentStatsViewer runat="server" ID="csvMain"></uc:ContentStatsViewer>

此控件还具有一些属性,这些属性设置为确定要显示的数据。其中一些属性委托给嵌入的ContentStatsViewer.ascx,如下所示:

public Data_Activities.ElementsRow Data_Element
{
    get => this.csvMain.Data_Element;
    set => this.csvMain.Data_Element = value;
}

最后,我通过动态加载在常规网页上使用我的NumericContentStatsViewer.ascx 控件。例如:

var ncsv = new NumericContentStatsViewer();
paMain.Controls.Add(ncsv);

我在Page_Load 事件处理程序上执行此操作,并且似乎工作正常。但是,一旦我尝试设置一个委托回嵌入式控件的属性,就会出现异常。例如,如果我执行以下操作:

ncsv.Data_Element = rElement;

...我在 Data_Element 属性设置器上收到 NullReferenceException,因为 this.csvMain 为空。

我不明白为什么这是空的。我尝试将其移至其他页面事件处理程序,例如 Page_LoadCompletePage_PreRender,结果相同。

有什么想法吗?谢谢。

【问题讨论】:

  • 您在哪个阶段(PreInit、Init、Load,...)添加控件? paMain.Controls.Add(ncsv);
  • 因为如果您在加载阶段加载它,则不会为控件调用 PreInit、Init 方法。这就是为什么它没有初始化它的任何孩子。
  • 而不是自己实例化它并将其添加到控件集合中,您应该更喜欢使用 LoadControl() 方法加载它,该方法将为您处理所需阶段处理程序方法的调用。
  • paMain.Controls.Add(ncsv) 在页面加载期间在转发器的事件处理程序上被调用。但请注意 paMain.Controls.Add(ncsv) 工作正常。不起作用的是后续的属性分配。
  • 是的,完全正确。 NumericContentStatsViewer.ascx 包含 ContentStatsViewer.ascx 并且这些(子控件)在 Init() 期间被初始化。当您使用new() 实例化控件时,只会调用构造函数。请您尝试两件简单的事情,1. 使用 LoadControl() 加载控件 2. 在 PreInit() 中执行此操作。看看 LoadControl 的第一句话:“当你将控件加载到容器控件中时,容器会引发所有添加的控件的事件,直到它赶上当前事件为止。”

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


【解决方案1】:

我已经重现了这个问题。

正如我的 cmets 中已经提到的,Web 用户控件的子控件在 Init() 阶段被实例化和初始化。

您有以下层次结构:

NumericContentStatsViewer
    ContentStatsViewer

NumericContentStatsViewer 控件内部的ContentStatsViewer 控件(csvMain 变量)由FrameworkInitialize 实例化并在Init 阶段初始化

当您自己在 Page_Load() 中实例化NumericContentStatsViewer 用户控件时,仅调用构造函数,而控件在 Asp.Net 生命周期不同阶段处理操作的方法未执行。

但是,如果您使用LoadControl() 方法加载控件,则

容器引发所有添加的控件的事件,直到它 赶上当前的事件。

https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.templatecontrol.loadcontrol?view=netframework-4.8

试试这个:

protected void Page_Load(object sender, EventArgs e)
{
    ...
    var ncsv = LoadControl("NumericContentStatsViewer.ascx") as NumericContentStatsViewer;
    ncsv.Data_Element = rElement;
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    相关资源
    最近更新 更多