I have a page and a user control — we'll call them Detail.aspx and Selector.ascx.
Let's say the page shows the details of individual records in a database. The user control basically consists of a DropDownList control and some associated HTML. The DropDownList displays a list of other records to switch to at any time.
When the DropDownList fires its SelectedIndexChanged event, I'd like the parent page, Detail.aspx in this case, to handle it. After all, he'll need to know what was selected so that he can appropriately change the URL and the details shown, etc.
To do that, I've done what I usually do, which is also what the top answer says to do in this StackOverflow question:
public event EventHandler DropDownSelectedIndexChanged
{
add
{
MyDropDownList.SelectedIndexChanged += value;
}
remove
{
MyDropDownList.SelectedIndexChanged -= value;
}
}
The above code appears in the Selector.ascx.cs codebehind file.
As a result, on Detail.aspx, I can use it like so:
<cc1:RecordSelector ID="RecordSelector1" runat="server"
OnDropDownSelectedIndexChanged="RecordSelector1_DropDownSelectedIndexChanged" />
So far nothing fancy or surprising.
Here is my problem:
This causes a NullReferenceException
when the browser hits Detail.aspx.
Debugging the problem shows that when the page is first hit, the public event I've shown above tries to add the event, but MyDropDownList is null, thus throwing the exception. From what I can tell, the events are added (or attempted to be added) before the Selector user control's Load event fires and thus also before the DropDownList's Load event fires.
Curiously, if I omit the OnDropDownSelectedIndexChanged attribute from Detail.aspx and instead put the following in the Page_Load event in Detail.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
RecordSelector1.DropDownSelectedIndexChanged += new EventHandler(RecordSelector1_DropDownSelectedIndexChanged);
}
It works exactly as expected. The events are attached and handled just fine. No problems.
But this means several bad things:
- I have to remember not to use the designer to add said event onto my user control
- I have to remember not to add the event via attributes when working in source view
- Worst of all, as the control's author I need to make sure everybody else using my control knows 1 and 2
So what am I doing wrong? Every example I've seen thus far shows similar usage of exposing child controls' events through a user control.