Подтвердить что ты не робот

Какое последнее событие срабатывает при загрузке нового окна WPF/С#?

Я пытаюсь загрузить окно настроек для своего приложения, и я бы хотел, чтобы кнопка Apply сначала была отключена, а затем, когда предпочтение обновляется, кнопка Apply снова включается. У меня есть данные управления, привязанные к объекту предпочтений, и что происходит, когда после загружается окно, события combobox запускаются. Есть ли какое-либо событие, которое, как гарантируется, будет мертвым в последний раз после того, как все будет стабильным?

Вот как выглядит мой код (кнопка приложения всегда включена после загрузки окна):

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _preferencesData = new PreferencesDataContext();
    LayoutRoot.DataContext = _preferencesData;
    ButtonApply.IsEnabled = false;
}

private void ComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
    ButtonApply.IsEnabled = true;
}

Интересно также отметить, что это происходит только с текстовыми полями и comboboxes, а не с флажками или радиообменами.

4b9b3361

Ответ 1

Лучшее решение для простой необходимости

Ответ Джозефа - наилучшее решение для вашей простой необходимости: просто используйте привязку данных и пусть модель данных обрабатывает ее.

Ответ на поставленный вопрос

Есть более сложные сценарии, когда вам действительно нужен контроль после того, как все закончилось, и все события уволились. Не существует единственного события, которое происходит "мертвым последним", но его легко свернуть самостоятельно, используя очередь диспетчера.

Вот как это сделать:

Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() =>
{
  var x = ComputeSomething(1, 2, 3);
  DoSomething(x, "Test");
}));

Все внутри {} будет выполнено, когда WPF завершит все с более высоким приоритетом, чем ContextIdle, который включает в себя все обработчики событий, загруженные события, события ввода, рендеринг и т.д.

Последовательность событий при создании и показе окна

В соответствии с запросом, вот последовательность основных событий в WPF при создании и отображении окна:

  • Конструкторы и геттеры/сеттеры вызываются по мере создания объектов, включая PropertyChangedCallback, ValidationCallback и т.д. для обновляемых объектов и любых объектов, которые наследуют от них.

  • Когда каждый элемент добавляется в визуальное или логическое дерево, его событие Intialized запускается, что вызывает поиск стилей и триггеров в дополнение к любой инициализации, специфичной для элемента, которую вы можете определить. [note: Инициализированное событие не запускается для листьев в логическом дереве, если в его корне нет PresentationSource (например, Window)]

  • Окно и все не скомпенсированные визуальные объекты на нем измеряются, что вызывает ApplyTemplate в каждом элементе управления, что вызывает дополнительную конструкцию дерева объектов, включая больше конструкторов и геттеров/сеттеров

  • Окно и все не скомпенсированные визуальные объекты на нем размещены

  • Окно и его потомки (как логические, так и визуальные) получают событие Loaded

  • Любые привязки данных, которые не выполнялись при их первом запуске, были повторно выполнены

  • Окно и его потомки получают возможность визуально визуализировать их содержимое

Шаги 1-2 выполняются, когда создается окно, независимо от того, отображается оно или нет. Другие шаги обычно не выполняются до тех пор, пока не будет показано окно, но они могут произойти раньше, если они запускаются вручную.

Ответ 2

Я просто делал одно и то же поведение в приложении WPF systray.

Однако я не делал этого, используя обработку событий. Я просто привязал свойство Enabled моей кнопки к свойству в моей модели ViewModel и обновлял свойство всякий раз, когда мне было нужно поведение.

Ответ 3

Событие Window.ContentRendered выполнило мои требования.

Ответ 5

Настройка DataContext скорее всего вызовет событие SelectionChanged, и вы не можете рассчитывать на то, когда именно он выстрелил. Некоторая логическая проверка того, что именно выбрано, будет более надежной:

private void ComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
    if (myComboBox.SelectedItem == null) 
    { 
      buttonApply.IsEnabled = false;
    }
    else 
    {
      buttonApply.IsEnabled = true;
    }
}

Причина, по которой это происходит после вашего кода как есть, заключается в том, что событие попадает в очередь в потоке для пользовательского интерфейса, поэтому оно до Windows, если оно выполнит следующую строку кода в Load или для обработки другие события в очереди.

Ответ 6

Не бросать на вас много вещей, с которыми вы можете или не знакомы, но если это относительно новая база кода, вы можете захотеть использовать шаблон MVVM и использовать Команды вместо архаичной (подчеркнутой моей) модели событий.