简介
INotifyPropertyChanged接口是 WPF 和其他支持数据绑定的 UI 框架中常用的一个接口,用于通知客户端(如 UI 控件)属性值已更改。当实现了这个接口的对象的属性值发生变化时,它会触发 PropertyChanged 事件,以便绑定的 UI 控件可以更新其显示以反映新的属性值。
以下是 INotifyPropertyChanged接口的定义:
using System.ComponentModel;
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
以下是一个简单的实现INotifyPropertyChanged接口的类的示例:
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class MyDataModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
使用
在WPF中,若你希望DataGrid能够实时展示ItemsSource所绑定List集合的变更,你需要确保该集合能够在内容变动时发出通知。然而,普通的List<T>并不具备此功能。为此,你可以选择使用ObservableCollection<T>替代List<T>,因为ObservableCollection<T>实现了INotifyCollectionChanged接口,能够在集合内容变更时自动通知DataGrid。
以下是一个简单的示例,展示了如何使用ObservableCollection<T>作为DataGrid的ItemsSource,并确保DataGrid能够实时反映集合的变更:
首先,定义一个数据模型:
public class MyDataModel
{
public string Name { get; set; }
public int Age { get; set; }
}
接着,在视图模型中创建一个ObservableCollection<MyDataModel>的实例,并将其作为DataGrid的ItemsSource:
public ObservableCollection<MyDataModel> Items { get; set; }
public MyViewModel()
{
Items = new ObservableCollection<MyDataModel>
{
new MyDataModel { Name = "Alice", Age = 30 },
new MyDataModel { Name = "Bob", Age = 25 }
};
}
在XAML文件中,将DataGrid的ItemsSource绑定到视图模型中的Items集合:
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="True"/>
现在,当你在代码中向Items集合添加、删除或修改项时,DataGrid会自动刷新以展示最新的数据。例如:
// 向集合中添加一个新项
Items.Add(new MyDataModel { Name = "Charlie", Age = 35 });
// 删除集合中的一个项
var itemToRemove = Items.FirstOrDefault(x => x.Name == "Bob");
if (itemToRemove != null)
{
Items.Remove(itemToRemove);
}
// 修改集合中的一个项
var itemToUpdate = Items.FirstOrDefault(x => x.Name == "Alice");
if (itemToUpdate != null)
{
itemToUpdate.Age = 31; // 由于MyDataModel的属性未实现INotifyPropertyChanged,此更改不会触发UI更新
// 若要触发UI更新,需确保MyDataModel实现INotifyPropertyChanged接口
}
请注意,若MyDataModel的属性值发生变更,并且你希望DataGrid能够实时展示这些变更,那么MyDataModel的属性需实现INotifyPropertyChanged接口。这样,在属性值变更时,DataGrid便能接收到通知并刷新显示。
以下是一个MyDataModel类实现INotifyPropertyChanged接口的示例:
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class MyDataModel : INotifyPropertyChanged
{
private string _name;
private int _age;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
public int Age
{
get { return _age; }
set
{
if (_age != value)
{
_age = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我们也可以使用自己实现的集合类,可以实现INotifyCollectionChanged接口,并在集合的Add、Remove、Clear等方法中触发CollectionChanged事件。
public class MyCollection<T> : IEnumerable<T>, INotifyCollectionChanged
{
private List<T> list = new List<T>();
public void Add(T item)
{
list.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
//...
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
CollectionChanged?.Invoke(this, e);
}
}
当然了,大多数ItemsSource 设置的对象都是 DataView ,DataGrid 会显示 DataView 中的数据,这些数据来自于与之关联的 DataTable。DataView 提供了对数据进行排序、筛选和搜索等功能,而这些更改都会实时反映在 DataGrid 上。
而且DataView 实现了 IBindingList 接口,该接口继承自 IList,并且提供了数据绑定和列表更改通知的功能。IBindingList 接口提供了类似 INotifyCollectionChanged 的功能,包括在列表更改时通知绑定的客户端。