У меня есть страница и пользовательский элемент управления -— мы будем называть их Detail.aspx и Selector.ascx.
Скажем, на странице показаны детали отдельных записей в базе данных. Пользовательский элемент управления в основном состоит из элемента управления DropDownList и некоторого связанного HTML. DropDownList отображает список других записей для переключения в любое время.
Когда DropDownList запускает событие SelectedIndexChanged, я бы хотел, чтобы в этом случае родительская страница Detail.aspx обрабатывала его. В конце концов, ему нужно знать, что было выбрано, чтобы он мог соответствующим образом изменить URL-адрес и отображаемые детали и т.д.
Чтобы сделать это, я сделал то, что я обычно делаю, что также говорит верхний ответ в qaru.site/questions/231241/...:
public event EventHandler DropDownSelectedIndexChanged
{
add
{
MyDropDownList.SelectedIndexChanged += value;
}
remove
{
MyDropDownList.SelectedIndexChanged -= value;
}
}
Вышеприведенный код появляется в файле кода Selector.ascx.cs.
В результате на Detail.aspx я могу использовать его так:
<cc1:RecordSelector ID="RecordSelector1" runat="server"
OnDropDownSelectedIndexChanged="RecordSelector1_DropDownSelectedIndexChanged" />
Пока ничего необычного или удивительного.
Вот моя проблема:
Это вызывает NullReferenceException
, когда браузер нажимает Detail.aspx.
Отладка проблемы показывает, что при первой попытке страницы публичное событие, показанное выше, пытается добавить событие, но MyDropDownList имеет значение NULL, тем самым бросая исключение. Из того, что я могу сказать, события добавляются (или пытались быть добавлены) до того, как пользовательский элемент управления Selector запускается, и, следовательно, также до того, как произойдет событие LoadDownList Load.
Любопытно, если я опускаю атрибут OnDropDownSelectedIndexChanged из Detail.aspx и вместо этого помещаю следующее в событие Page_Load в Detail.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
RecordSelector1.DropDownSelectedIndexChanged += new EventHandler(RecordSelector1_DropDownSelectedIndexChanged);
}
Он работает точно так, как ожидалось. События прилагаются и обрабатываются просто отлично. Нет проблем.
Но это означает несколько плохих вещей:
Так что я делаю неправильно? Каждый пример, который я видел до сих пор, показывает аналогичное использование экспонирования событий дочерних элементов управления через пользовательский элемент управления.
Причина, по которой это работает:
protected void Page_Load(object sender, EventArgs e)
{
RecordSelector1.DropDownSelectedIndexChanged
+= new EventHandler(RecordSelector1_DropDownSelectedIndexChanged);
}
и это не так:
<cc1:RecordSelector ID="RecordSelector1" runat="server"
OnDropDownSelectedIndexChanged="RecordSelector1_DropDownSelectedIndexChanged" />
заключается в том, что первый добавляет обработчик после инициализации элемента управления (через страницу Init
). Второй пример анализируется намного раньше, и таким образом страница пытается добавить обработчик перед инициализацией элемента управления.
Из-за характера жизненного цикла страницы, я думаю, вам, возможно, придется жить с добавлением обработчика событий в код. Не будет способа добавить обработчик перед инициализацией элемента управления, потому что перед инициализацией этот элемент всегда будет null
.