当WPF数据网格选择不可见时,INotifyPropertyChanged的空引用异常
本文关键字:INotifyPropertyChanged 异常 引用 数据 WPF 数据网 网格 选择 | 更新日期: 2023-09-27 18:15:38
我有一个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;
如果在错误发生时检查所选值列表的值,则所有所选项都将被检测到。似乎当他们不可见时,事件发生了一些事情。
为什么项目在视图中的可见性会影响事件处理程序是否为空?
这样修改代码:
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框架版本,你还可以改进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]
会自动给你调用者的名字。
这(可能)会减少输入,减少代码中由于拼写错误或属性名称更改而导致的错误的空间。
使用任何事件处理程序的最佳实践是在调用它之前测试是否为null…
if(PropertyChanged != null) this.PropertyChanged....
我也很好奇为什么你会让一个字符串。是否使用空的默认值?
因为处理程序是在WPF中创建的,而不是在代码中显式创建的,所以您无法控制处理程序是否存在-添加检查,您应该可以。
更简单:
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
和
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
1行vs 2行