Почему мои дочерние элементы управления не были инициализированы во время прикрепления события?

2

У меня есть страница и пользовательский элемент управления -— мы будем называть их 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);
}

Он работает точно так, как ожидалось. События прилагаются и обрабатываются просто отлично. Нет проблем.

Но это означает несколько плохих вещей:

  • Я должен помнить, чтобы не использовать конструктор для добавления указанного события в мой пользовательский элемент управления
  • Я должен помнить, что нельзя добавлять событие через атрибуты при работе в представлении источника
  • Хуже всего, как автор контроля, мне нужно убедиться, что все, кто использует мой контроль, знают 1 и 2

Так что я делаю неправильно? Каждый пример, который я видел до сих пор, показывает аналогичное использование экспонирования событий дочерних элементов управления через пользовательский элемент управления.

  • 0
    Ваш раскрывающийся список в пользовательском элементе управления определен в разметке или он добавляется в коде?
  • 0
    Это в разметке, да. Элемент управления не добавляется программно / динамически.
Теги:
user-controls
events

1 ответ

1
Лучший ответ

Причина, по которой это работает:

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.

  • 0
    Есть ли способ сделать это без этой ловушки? «Скотт Гу» - рекомендуемый подход к представлению событий дочерних элементов управления в пользовательском элементе управления?
  • 0
    Я бы хотел порекомендовать другой подход, но я думаю, что раскрытие события с помощью пользовательского элемента управления - ваш лучший вариант, так как любой потребитель события должен нести ответственность за его подключение таким образом, чтобы он работал для них.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню