Nested ASP.NET user control is null

558 Views Asked by At

I am developing an ASP.NET application using Visual Studio 2017 and .NET 4.7.1. I have a simple user control, named ContentStatsViewer.ascx, that that displays a couple of labels. The values to display are passed through public properties.

Other controls such as NumericContentStatsViewer.ascx include an instance of ContentStatsViewer.ascx along other content, like this:

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

This control also has some properties that are set to establish what data to display. Some of these properties delegate back to those of the embedded ContentStatsViewer.ascx, like this:

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

Finally, I use my NumericContentStatsViewer.ascx control on regular web pages by dynamically loading it. For example:

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

I am doing this on the Page_Load event handler, and seems to work fine. However, as soon as I try to set a property that delegates back to the embedded control, I get an exception. For example, if I do the following:

ncsv.Data_Element = rElement;

...I get a NullReferenceException on the Data_Element property setter because this.csvMain is null.

I don't understand why this is null. I have tried moving it to other page event handlers such as Page_LoadComplete or Page_PreRender, with identical results.

Any ideas? Thank you.

1

There are 1 best solutions below

0
On BEST ANSWER

I've reproduced the problem.

As already mentioned in my comments, the child controls of a web user control are instantiated and initialized during the Init() phase.

You have the following hierarchy:

NumericContentStatsViewer
    ContentStatsViewer

The ContentStatsViewer control (the csvMain variable) inside the NumericContentStatsViewer control is instantiated byFrameworkInitialize and initialized during the Init phase

When you instantiate the NumericContentStatsViewer user control in Page_Load() yourself, only the constructor is invoked and the control's methods for handling the operations during different stages of Asp.Net life cycle are left unexecuted.

But, if you load your control using the LoadControl() method,

the container raises all of the added control's events until it has caught up to the current event.

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

Try this:

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