如何将Dictionary<int,foo>绑定DataGrid并实时同步变更?
解决方案:自定义可观察字典实现实时UI更新
问题根源在于.NET原生Dictionary<TKey, TValue>没有实现INotifyCollectionChanged和INotifyPropertyChanged接口,所以当你对字典执行增、删、替换元素操作时,UI无法自动感知这些变化,只有在集合引用被替换或UI强制刷新时才会更新。
要解决这个问题,你可以自定义一个ObservableDictionary,让它同时具备字典的高效查找能力和集合变更通知功能。以下是具体实现步骤:
1. 实现ObservableDictionary<TKey, TValue>
创建一个继承自Dictionary<TKey, TValue>并实现INotifyCollectionChanged、INotifyPropertyChanged接口的类:
using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; public class ObservableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged { public event NotifyCollectionChangedEventHandler CollectionChanged; public event PropertyChangedEventHandler PropertyChanged; public new void Add(TKey key, TValue value) { base.Add(key, value); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value))); } public new bool Remove(TKey key) { if (base.TryGetValue(key, out var value)) { var result = base.Remove(key); if (result) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value))); } return result; } return false; } public new void Clear() { var items = new List<KeyValuePair<TKey, TValue>>(this); base.Clear(); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } public new TValue this[TKey key] { get => base[key]; set { if (base.TryGetValue(key, out var oldValue)) { base[key] = value; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, oldValue))); } else { base[key] = value; OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value))); } OnPropertyChanged(nameof(Count)); OnPropertyChanged(nameof(Keys)); OnPropertyChanged(nameof(Values)); } } protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { CollectionChanged?.Invoke(this, e); } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 修改你的Database1定义
将原来的Dictionary<int, ToolType>替换为自定义的ObservableDictionary<int, ToolType>:
public ObservableDictionary<int, ToolType> DicToolType { get; set; } = new ObservableDictionary<int, ToolType>();
3. 确保ToolType实现属性变更通知
如果需要实时更新ToolType内部属性(比如Name、Type)的变化,你的ToolType类必须实现INotifyPropertyChanged接口:
public class ToolType : INotifyPropertyChanged { private string _name; private string _type; public string Name { get => _name; set { if (_name != value) { _name = value; OnPropertyChanged(nameof(Name)); } } } public string Type { get => _type; set { if (_type != value) { _type = value; OnPropertyChanged(nameof(Type)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
4. 保持原有XAML绑定不变
你的DataGrid绑定代码不需要修改,因为ObservableDictionary的枚举结果仍然是KeyValuePair<int, ToolType>,和原生Dictionary一致:
<DataGrid ItemsSource="{Binding DicToolType}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" IsReadOnly="True"> <DataGrid.Columns> <DataGridTextColumn FontSize="12" Width="60" Header="T" Binding="{Binding Key}"/> <DataGridTextColumn FontSize="12" Width="100" Header="Name" Binding="{Binding Value.Name}"/> <DataGridTextColumn FontSize="12" Width="90" Header="Type" Binding="{Binding Value.Type}"/> </DataGrid.Columns> </DataGrid>
关键说明
- 自定义的
ObservableDictionary在执行增、删、替换元素操作时,会触发CollectionChanged事件,通知UI更新。 - 当修改字典中已有键对应的值时,会触发
Replace类型的变更通知;新增键值对触发Add,删除触发Remove,清空触发Reset。 ToolType实现INotifyPropertyChanged后,其内部属性的修改会自动同步到UI,无需额外处理。
内容的提问来源于stack exchange,提问作者tstx
相关产品推荐
相关产品推荐

