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

时间:2010-03-25 18:12:16

标签: c# wpf

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

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

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

我看到的其他解决方案是

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

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

6 个答案:

答案 0 :(得分:27)

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

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:4)

您应该能够检查窗口上的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 ...
}

答案 3 :(得分:1)

我有同样的问题,我认为这是一个错误。我发现了一个解决方法: 我删除了'Ischecked&#39;来自Xaml并在init

后面的代码中设置它

答案 4 :(得分:0)

是否有任何控件使用双向数据绑定?我遇到过这个问题,我将文本框绑定到ViewModel上的属性。 ViewModel初始化触发INotifyPropertyChanged直到绑定控件,这反过来导致文本框的TextChanged事件触发。我的短期解决方法是将事件订阅移动到Loaded事件窗口,但就像你说的那样,这是一种痛苦。我需要重构代码以更改对象初始化的顺序,以便在ViewModel之前创建WPF视图(即窗口和用户控件)。然后,我将能够将事件处理程序注册移回XAML。

答案 5 :(得分:0)

Window Control在初始化可以检查并设置为初始值的子控件时触发已检查事件。

我强烈认为这是一个错误。只是它从MFC程序集中深处触发NullReferenceException这一事实应该足以让人意料到这是非预期的行为。

考虑到Xaml编辑器在Control部分类中创建处理函数,如果此类未完成构造,则无法处理事件。我不认为为控件启动一个已检查的事件,你的设置初始化为检查似乎是正确的。

我的意思是,如果您将其初始状态设置为未选中状态,是否会触发未经检查的事件?