在InitializeComponent期间WPF获取控件空引用

red*_*der 15 c# wpf

所以我InitializeComponent在Window的构造函数中的方法调用正在运行XML并添加控件并将它们插入到它们的事件中.

因此,当其中一个控件的属性发生更改时,它会调用订阅该事件的Method.该方法引用尚未构建的控件.

为什么这会按此顺序发生?它在WinForms中有效,因为在创建所有控件之后,事件才会被激活.有没有办法在WPF中强制执行此操作?

我看到的其他解决方案是

  • 我需要在初始化后订阅事件.

  • 每当我处理一个控件时,我都需要检查null.

Jor*_*ger 28

我也遇到了这个问题,并通过在null检查中包含访问空控件的行来解决它.这似乎是一个黑客的解决方法.

我认为WPF通过在InitializeComponent()期间调用Checked事件来尝试提供帮助,以确保根据复选框的初始状态执行任何UI逻辑(例如显示/隐藏相关组件).我测试默认情况下取消选中Checkbox,并且未调用事件处理程序,即使我已将其连接到Checked和Unchecked事件.我甚至在一个空白的WPF项目中重现了这一点,屏幕上有一个Checkbox,它的行为相同.

此默认行为的问题显然是某些其他组件尚未初始化.我认为WPF应该等到所有组件都被初始化,然后默认触发Checked事件.这可能不会被视为错误,但无论如何我都会在相关的MSDN页面上添加注释...


Cod*_*ked 5

您应该能够检查 Window 上的 IsInitialized 或 IsLoaded 属性,以验证它已完成初始化/加载。否则,您需要检查 null 或在后面的代码中(在 InitializeComponent 之后)添加您的事件订阅。

此外,您可以调整访问元素的方式。例如,如果你有类似的东西:

<ListBox x:Name="listBox" SelectionChanged="OnListBoxSelectionChanged" />
Run Code Online (Sandbox Code Playgroud)

然后在你后面的代码中你可以通过几种方式获得列表框:

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 ...
}
Run Code Online (Sandbox Code Playgroud)


red*_*der 5

这是一个无线电按钮上的Checked事件.当我从xaml中删除Checked ="true"时,问题就消失了.(虽然在Window启动时会检查它).不确定这里发生了什么,但至少我没有必要改变任何重要的东西来修复它......