1

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.

CesarGon
  • 15,099
  • 6
  • 57
  • 85
  • 1
    In whic phase (PreInit, Init, Load, ...) are you adding the control? `paMain.Controls.Add(ncsv);` – Oguz Ozgul Mar 23 '20 at 20:11
  • Because if you are loding it during the Load phase, the PreInit, Init methods will not have been invoked for the control. That's why it is not initializing any of its children. – Oguz Ozgul Mar 23 '20 at 20:13
  • And instead of instantiating it yourself and adding it to the controls collection, you should prefer loading it using the `LoadControl()` method which will handle the invocation of the required stage handler methods for you. – Oguz Ozgul Mar 23 '20 at 20:16
  • paMain.Controls.Add(ncsv) is being invoked on an event handler for a repeater during page load. But please note that paMain.Controls.Add(ncsv) works fine. What doesn't work is the subsequent property assignment. – CesarGon Mar 23 '20 at 23:08
  • Yes, exactly. `NumericContentStatsViewer.ascx` contains a `ContentStatsViewer.ascx` and these (child controls) are initialized during Init(). When you instantiate the control with `new()`, only the constructor is called. Can you please try two simple things, 1. load the control using LoadControl() 2. Do this in PreInit() . Look at the first remark of LoadControl: "When you load a control into a container control, the container raises all of the added control's events until it has caught up to the current event." – Oguz Ozgul Mar 23 '20 at 23:45

1 Answers1

1

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;
    ...
}
Oguz Ozgul
  • 6,809
  • 1
  • 14
  • 26