加载新的WPF / C#窗口时要触发的最后一个事件是什么?

我正在尝试为我的应用程序加载首选项窗口,我希望最初禁用应用按钮,然后在更新首选项时,再次启用应用按钮。 我有一些绑定到首选项对象的控件数据,发生的情况是窗口加载后,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; } 

是否有趣的是,这只发生在文本框和combobox中,而不是复选框或单选按钮。

简单需求的最佳解决方案

对于您的简单需求,Joseph的答案是迄今为止最好的解决方案:只需使用数据绑定并让数据模型处理它。

回答提出的问题

在完全加载所有事件并且所有事件都被触发之后,当你确实需要控制时,有更复杂的场景。 没有单个事件发生在“死后”,但使用Dispatcher队列很容易有效地滚动自己的事件。

这是怎么做的:

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

当WPF以比ContextIdle更高的优先级完成所有内容时,{}内的所有内容都将被执行,后者包括所有事件处理程序,加载的事件,输入事件,呈现等。

创建和显示窗口时的事件序列

根据要求,这是创建和显示窗口时WPF中的主要事件序列:

  1. 在创建对象时调用构造函数和getter / setter,包括对正在更新的对象的PropertyChangedCallback,ValidationCallback等以及从它们inheritance的任何对象

  2. 当每个元素被添加到可视或逻辑树时,它的Intialized事件被触发,这导致除了您可能定义的任何特定于元素的初始化之外还应用样式和触发器[注意:逻辑树中的叶子不会触发初始化事件如果根源没有PresentationSource(例如Window)

  3. 窗口和所有未折叠的Visuals都是Measured,这会在每个Control上产生一个ApplyTemplate,这会导致额外的对象树构造,包括更多的构造函数和getter / setter

  4. 窗口和所有未折叠的Visuals都是Arranged

  5. 窗口及其后代(逻辑和可视)接收Loaded事件

  6. 重试首次设置失败的任何数据绑定

  7. 窗口及其后代有机会在视觉上呈现其内容

无论是否显示Window,都会在创建Window时完成步骤1-2。 其他步骤通常在窗口显示之前不会发生,但如果手动触发它们可以更早发生。

我只是在systray WPF应用程序中做了同样的事情。

但是,我没有使用事件处理。 我只是将我的按钮的Enabled属性绑定到我的ViewModel中的属性,并在需要该行为时更新属性。

Window.ContentRendered事件满足了我的要求。

您可以使用ManagedSpy自行解决这个问题。

http://msdn.microsoft.com/en-us/magazine/cc163617.aspx

设置DataContext可能会触发SelectionChanged事件,并且您无法依赖于何时触发它。 对确切选择的内容进行一些逻辑检查会更可靠:

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

之后使用您的代码发生的原因是因为事件在UI的线程上排队,所以如果它将在Load执行下一行代码,或者处理队列中的其他事件,则由Windows决定。

不要向你抛出很多你可能熟悉或不熟悉的东西,但如果这是一个相对较新的代码库,你可能要考虑使用MVVM模式并使用命令而不是古老的 (强调我的)事件模型。

Windows窗体中的事件顺序

Control.HandleCreated

Control.BindingContextChanged

Form.Load

Control.VisibleChanged

Form.Activated

Form.Shown