自定义BindableDictionary绑定BindingSource后内部列表不刷新问题
问题描述
尝试将Dictionary<string, string>绑定到BindingSource,并作为WinForm中ListBox控件的DataSource,但未生效。随后发现Dictionary未实现BindingSource正常工作所需的INotifyPropertyChanged接口,此前相关主题的解决方案对我并无帮助。
尝试的解决方案
为满足BindingSource的约束,编写了实现必要接口的自定义字典类BindableDictionary,最终代码如下:
public class BindableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyPropertyChanged { private readonly IDictionary<TKey, TValue> dictionary; public BindableDictionary() : this(new Dictionary<TKey, TValue>()) { } public BindableDictionary(IDictionary<TKey, TValue> dict) { dictionary = dict; } public TValue this[TKey key] { get => dictionary[key]; set => ReflectChange(key, value); } public int Count => dictionary.Count; public bool IsReadOnly => dictionary.IsReadOnly; public ICollection<TKey> Keys => dictionary.Keys; public ICollection<TValue> Values => dictionary.Values; protected virtual event PropertyChangedEventHandler PropertyChanged; event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { add { PropertyChanged += value; } remove { PropertyChanged -= value; } } protected virtual void OnPropertyChanged(string property) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value); public void Add(TKey key, TValue value) => ReflectAdd(key, value); public void Clear() { dictionary.Clear(); OnPropertyChanged("Count"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); } public bool Contains(KeyValuePair<TKey, TValue> item) => dictionary.Contains(item); public bool ContainsKey(TKey key) => dictionary.ContainsKey(key); public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => dictionary.CopyTo(array, arrayIndex); public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => dictionary.GetEnumerator(); public bool Remove(KeyValuePair<TKey, TValue> item) => ReflectRemove(item.Key); private bool ReflectRemove(TKey key) { if (dictionary.TryGetValue(key, out TValue value) && dictionary.Remove(key)) { OnPropertyChanged("Count"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Item[]"); return true; } return false; } private void ReflectAdd(TKey key, TValue value) { dictionary.Add(key, value); OnPropertyChanged("Count"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Item[]"); } private void ReflectChange(TKey key, TValue value) { if (dictionary.TryGetValue(key, out TValue oldValue)) { dictionary[key] = value; OnPropertyChanged("Values"); OnPropertyChanged("Item[]"); } else { ReflectAdd(key, value); } } public bool Remove(TKey key) => ReflectRemove(key); public bool TryGetValue(TKey key, out TValue value) => dictionary.TryGetValue(key, out value); IEnumerator IEnumerable.GetEnumerator() => dictionary.GetEnumerator(); }
public partial class Form1 : Form { BindableDictionary<string, string> AttachDictionary = new BindableDictionary<string, string>(); BindingSource AttachSource; public Form1() { InitializeComponent(); listBox1.DisplayMember = "Key"; listBox1.ValueMember = "Value"; listBox1.DataSource = AttachSource = new BindingSource(AttachDictionary, null); } private void button1_Click(object sender, EventArgs e) { using (OpenFileDialog OFD = new OpenFileDialog()) { if (OFD.ShowDialog() == DialogResult.OK) { AttachDictionary.Add(OFD.SafeFileName, OFD.FileName); AttachSource.ResetBindings(false); } } } }
问题现状
- 尽管已实现接口,但
DataSource更新后,BindingSource的内部List对象仍未刷新,ListBox无法显示新增项。 - 使用
ObservableCollection替代可与BindingSource正常配合工作,但因知识有限暂不清楚原因,尝试查看源码但内容过于庞大。 - 推测
DataSource的变更未正确传递,导致BindingSource未感知到更新,可能是事件绑定存在问题。
内容的提问来源于stack exchange,提问作者Abhinav Pandey
相关产品推荐
相关产品推荐

