当WPF DataGrid选择不可见时,INotifyPropertyChanged的空引用异常?

时间:2014-07-30 05:39:30

标签: c# wpf datagrid nullreferenceexception

我有一个DataGrid控件,用户可以在其中选择多个项目。选择项目并按下按钮后,我遍历每个项目并编辑属性。更改此属性后,INotifyPropertyChanged事件将触发。一切都很美妙。但是我注意到如果我选择两个或更多项并滚动以使其中一个项目远离视图而然后按下按钮,程序将崩溃并给出我是NotifyPropertyChanged()方法中的空引用异常,告诉我PropertyChangedEventHandler为空。如果我从属性的setter中删除NotifyPropertyChanged()调用,代码会正常工作,所以现在我正在做的事情,但为什么会这样呢?如果我只选择了一个项目,无论滚动位置如何,它都可以正常工作。

在我实现INotifyPropertyChanged接口的模型类中,我有以下内容:

    public event PropertyChangedEventHandler PropertyChanged;
    // ...
    public bool IsScheduled
    {
        get { return isScheduled; }
        set { isScheduled = value; NotifyPropertyChanged(self.ToString()); }
    }
    // ...
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

在ViewModel的其他地方,我进行这个简单的调用,触发错误:

process.IsScheduled = true;

如果在发生错误时检查所选值列表的值,则会检测到所有选定的项目 。当事件不可见时,似乎会发生一些事情。

为什么视图中项目的可见性会影响事件处理程序是否为空?

3 个答案:

答案 0 :(得分:3)

更改您的代码:

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));
}

始终检查null,因为如果没有附加事件处理程序,它将抛出NullReferenceException除此之外,在引发事件时应始终使用temp变量,因为任何对象都可以随时添加/删除处理程序。

修改

根据您的.NET Framework版本,您还可以改进INotifyPropertyChanged实现

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "" )
{
    var handler = PropertyChanged;
    if (handler != null)
        handler(this, new PropertyChangedEventArgs(propertyName));
}

然后简单地使用NotifyPropertyChanged();通知,而不显式将属性名称传递给方法,因为[CallerMemberName]会自动为您提供调用者的名称。

由于拼写错误或更改了属性名称,这可能会导致代码中的错误减少,错误空间也会减少。

答案 1 :(得分:1)

任何事件处理程序的最佳实践是在调用它之前测试null ...

if(PropertyChanged != null) this.PropertyChanged....

我也很好奇你为什么要使用string.empty默认值?

因为处理程序是在WPF中创建的而不是在代码中显式创建的,所以您无法控制是否存在处理程序 - 添加检查并且您应该没问题。

答案 2 :(得分:0)

甚至更简单:

pip install .\wxPython-4.0.0a1-cp27-cp27m-win_amd64.whl

vs

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));

1行vs 2