c# - INotifyPropertyChanged 不更新 Windows 窗体中的列表框
问题描述
Listbox
每当将新的“键”、“值”添加到字典中时,我都会尝试更新。
我有一个实现IDictionary
和INotifyPropertyChanged
(从 MSDN 复制)的类,它有一个方法 Add。(我没有添加其他方法来保持问题简短);
public class SimpleDictionary : IDictionary, INotifyPropertyChanged
{
public DictionaryEntry[] items;
public Int32 ItemsInUse = 0;
public void Add(object key, object value)
{
// Add the new key/value pair even if this key already exists in the dictionary.
if (ItemsInUse == items.Length)
throw new InvalidOperationException("The dictionary cannot hold any more items.");
items[ItemsInUse++] = new DictionaryEntry(key, value);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("key"));
}
}
在 Main void 方法中,我有以下内容:
public static SimpleDictionary clients = new SimpleDictionary(3);
static void Main()
{
clients.Add("key1", "Value1");
display_List();
clients.PropertyChanged += Clients_PropertyChanged;
}
private static void Clients_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show("Dictionary changed: "+e.PropertyName);
}
static void display_List()
{
try {
form_m.listBox1.DataSource = new BindingSource(clients,null);
form_m.listBox1.DisplayMember = "key";
}
catch (Exception e) {
form_m.Program_console_1("Displat Binding Error: "+e.ToString());
}
}
public static void Update_Dictionary(object sender, System.EventArgs e)
{
clients.Add("key3","Value3");
}
程序启动时listBox1
初始化并将“key1”、“value”添加到“clients”。方法display_List
绑定clients
并显示所有键。
当我调用Update_Dictionary
方法“key2”,“value2”被添加并被Clients_PropertyChanged
触发。但是,listbox1
并不反映新添加的密钥,即“key2”。它仍然只显示“key1”。
如果我再次添加数据源,则会显示“key1”和“key2”。需要做什么才能在自动调用 Clients_PropertyChanged 时更新列表框?
更新:尝试使用 INotifyCollectionChanged 仍然是同样的问题
他是我正在使用的完整课程
using System;
using System.Collections;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
namespace x_server
{
// This class implements a simple dictionary using an array of DictionaryEntry objects (key/value pairs).
class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string CountString = "Count";
private const string IndexerName = "Item[]";
private const string KeysName = "Keys";
private const string ValuesName = "Values";
private IDictionary<TKey, TValue> _Dictionary;
protected IDictionary<TKey, TValue> Dictionary
{
get { return _Dictionary; }
}
#region Constructors
public ObservableDictionary()
{
_Dictionary = new Dictionary<TKey, TValue>();
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
{
_Dictionary = new Dictionary<TKey, TValue>(dictionary);
}
public ObservableDictionary(IEqualityComparer<TKey> comparer)
{
_Dictionary = new Dictionary<TKey, TValue>(comparer);
}
public ObservableDictionary(int capacity)
{
_Dictionary = new Dictionary<TKey, TValue>(capacity);
}
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
{
_Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
}
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
{
_Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
}
#endregion
#region IDictionary<TKey,TValue> Members
public void Add(TKey key, TValue value)
{
Insert(key, value, true);
}
public bool ContainsKey(TKey key)
{
return Dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return Dictionary.Keys; }
}
public bool Remove(TKey key)
{
if (key == null) throw new ArgumentNullException("key");
TValue value;
Dictionary.TryGetValue(key, out value);
var removed = Dictionary.Remove(key);
if (removed)
//OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));
OnCollectionChanged();
return removed;
}
public bool TryGetValue(TKey key, out TValue value)
{
return Dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return Dictionary.Values; }
}
public TValue this[TKey key]
{
get
{
return Dictionary[key];
}
set
{
Insert(key, value, false);
}
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
public void Add(KeyValuePair<TKey, TValue> item)
{
Insert(item.Key, item.Value, true);
}
public void Clear()
{
if (Dictionary.Count > 0)
{
Dictionary.Clear();
OnCollectionChanged();
}
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return Dictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Dictionary.CopyTo(array, arrayIndex);
}
public int Count
{
get { return Dictionary.Count; }
}
public bool IsReadOnly
{
get { return Dictionary.IsReadOnly; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return Dictionary.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Dictionary).GetEnumerator();
}
#endregion
#region INotifyCollectionChanged Members
public event NotifyCollectionChangedEventHandler CollectionChanged;
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
public void AddRange(IDictionary<TKey, TValue> items)
{
if (items == null) throw new ArgumentNullException("items");
if (items.Count > 0)
{
if (Dictionary.Count > 0)
{
if (items.Keys.Any((k) => Dictionary.ContainsKey(k)))
throw new ArgumentException("An item with the same key has already been added.");
else
foreach (var item in items) Dictionary.Add(item);
}
else
_Dictionary = new Dictionary<TKey, TValue>(items);
OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
}
}
private void Insert(TKey key, TValue value, bool add)
{
if (key == null) throw new ArgumentNullException("key");
TValue item;
if (Dictionary.TryGetValue(key, out item))
{
if (add) throw new ArgumentException("An item with the same key has already been added.");
if (Equals(item, value)) return;
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
}
else
{
Dictionary[key] = value;
OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
}
}
private void OnPropertyChanged()
{
OnPropertyChanged(CountString);
OnPropertyChanged(IndexerName);
OnPropertyChanged(KeysName);
OnPropertyChanged(ValuesName);
}
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private void OnCollectionChanged()
{
OnPropertyChanged();
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
{
OnPropertyChanged();
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
{
OnPropertyChanged();
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems)
{
OnPropertyChanged();
if (CollectionChanged != null) CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems));
}
}
}
解决方案
INotifyPropertyChanged
如果属性的值发生变化,则使用。集合本身不会改变,它的内容会改变。这由另一个接口发出信号:INotifyCollectionChanged
.
您不需要自定义集合类型,要在更新集合时获取更新,请改用ObservableCollection。
编辑:我刚刚意识到ObservableCollection
默认情况下在 Windows 窗体中不可用,但看起来您可以轻松添加它。
推荐阅读
- python - 如何从python中的df中提取每小时数据?
- amazon-web-services - Does the alarm monitor the whole autoscaling group
- antlr - 空格和 int 文字/二元运算符的问题
- php - Laravel 路由模型绑定 - 资源控制器
- java - java 8流收集最大对象并按属性区分
- matlab - Matlab c2d 函数提供与 Z 变换表不同的输出
- neo4j - 新4j;复杂密码查询
- windows - 使用 xcopy 在文件结构处复制的问题
- vue.js - 使用 Vuetify 在文本字段标签旁边显示工具提示图标
- java - 如何在现有的 Camel Jetty REST 路线上添加 matchOnUriPrefix?