WPF Получение контрольной нулевой ссылки во время InitializeComponent

Итак, мой вызов метода InitializeComponent в конструкторе Window работает через XML и добавляет элементы управления и подключает их к своим событиям.

Поэтому, когда свойство одного из элементов управления изменяется, он вызывает метод, который подписывается на событие. Метод ссылается на элемент управления, который еще не создан.

Почему это происходит в этом порядке здесь? Он работал в WinForms, потому что события не запускались до тех пор, пока не были созданы все элементы управления. Есть ли способ заставить это в WPF?

Другие решения, которые я вижу,

  • Мне нужно подписаться на события после инициализации. Это боль в дерьме.

  • Мне нужно проверять значение null, когда я общаюсь с элементом управления. Также боль в дерьме, с добавлением боли.

Любая помощь?

Ответы

Ответ 1

У меня тоже была эта проблема, и я решил ее, обернув строку, обратную нулевому элементу управления, в нулевой проверке. Это похоже на небольшое обходное решение.

Я думаю, что WPF пытается помочь здесь, вызвав наше проверенное событие во время InitializeComponent(), чтобы гарантировать, что любая логика пользовательского интерфейса (например, отображение/скрытие связанных компонентов) выполняется на основе исходного состояния флажка. Я протестировал флажок, отмеченный флажком по умолчанию, и обработчик события не вызывается, хотя я его подключил как к проверенным, так и к непроверенным событиям. Я даже воспроизвел это в пустом проекте WPF с одним флажком на экране, и он ведет себя одинаково.

Проблема с этим поведением по умолчанию, очевидно, что некоторые из других компонентов еще не инициализированы. Я думаю, WPF должен ждать, пока все компоненты не будут инициализированы, прежде чем запускать событие Checked по умолчанию. Это может не считаться ошибкой, но я все равно добавлю заметку на соответствующую страницу MSDN...

Ответ 2

Это событие было проверено на радиобарабане. Когда я удалил Checked = "true" из xaml, проблема исчезла. (хотя он проверяется при запуске окна). Не уверен, что происходит здесь, но по крайней мере мне не пришлось ничего менять, чтобы исправить это... пока.

Ответ 3

Вы должны иметь возможность проверить свойства IsInitialized или IsLoaded в своем окне, чтобы убедиться, что он завершил инициализацию/загрузку. В противном случае вам нужно будет проверить значение null или добавить подписки на события в свой код позади (после InitializeComponent).

Кроме того, вы можете настроить способ доступа к элементам. Например, если у вас есть что-то вроде:

<ListBox x:Name="listBox" SelectionChanged="OnListBoxSelectionChanged" />

Затем в вашем коде вы можете получить окно списка несколькими способами:

private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) {
    ListBox lb = this.listBox; // May be null
    ListBox lb = sender as ListBox; // Should never be null
    ListBox lb = e.Source as ListBox; // Same as sender in this case
    ListBox lb = e.OriginalSource as ListBox; // Always the element that started the event (if handler is not attached directly to ListBox).
    // ... Do Something ...
}

Ответ 4

У меня была такая же проблема, и я думаю, что это ошибка. Я нашел обходное решение: Я удалил "Ischecked" из Xaml и установил его в коде после init

Ответ 5

Есть ли какое-либо из элементов управления, использующее двустороннюю привязку данных? Я столкнулся с этой проблемой, когда у меня были текстовые поля, привязанные к свойствам в ViewModel. Инициализация ViewModel запускала INotifyPropertyChanged до связанного элемента управления, что, в свою очередь, вызывало событие TextChanged в текстовом поле. Моим краткосрочным обходным решением было перевести подписку на событие в событие "Загружено", но, как вы заявили, такая боль. Мне нужно реорганизовать код, чтобы изменить порядок в том, как мои объекты инициализируются, чтобы WPF-представления (то есть окна и пользовательские элементы управления) создавались перед ViewModels. Затем я смогу перенести регистрацию обработчика событий обратно в XAML.

Ответ 6

Контроль окна запускает проверенные события при инициализации вспомогательных элементов управления, которые могут быть проверены и установлены в качестве начального значения.

Я твердо придерживаюсь мнения, что это ошибка. Просто тот факт, что он запускает исключение NullReferenceException из глубины внутри сборки MFC, должен быть достаточным, чтобы ожидать, что это непреднамеренное поведение.

Учитывая, что редактор Xaml создает функции обработчика в вашем частичном классе Control, и если этот класс не завершен, он не может обрабатывать события. Я не думаю, что уволил проверенное событие для управления, которое ваша настройка была инициализирована проверкой, кажется правильной.

Я имею в виду, должен ли он запускать событие Unchecked, если вы установили его начальное состояние на флажок?