我正在使用WPF和C# 我有一个打开窗口的按钮,其中还包含一个按钮,用于将用户对象项添加到列表框中,我希望在插入后更新列表框索引。我明白解决方案是关于使用可观察的INotifyCollectionChanged类,但实际上我不知道如何以及在何处使用它们。你能帮我确定实施,注册,开火等的内容和地点。
编辑: 我在Quartermeister的帮助下成功完成了我的用户对象收集在列表中,但现在我想做同样的事情,我的对象被收集在字典中
答案 0 :(得分:4)
最简单的方法是使用System.Collections.ObjectModel.ObservableCollection<T>
作为列表。这会为您实现INotifyCollectionChanged
和INotifyPropertyChanged
。
您将在此类型的DataContext对象上拥有一个属性,并使用ListBox.ItemsSource上的数据绑定将其绑定到该属性。当集合发生更改时,ListBox将自动更新其元素列表。
在您的DataContext类中:
public class MyClass
{
public ObservableCollection<string> Items { get; set; }
}
在Xaml中:
<ListBox ItemsSource="{Binding Items}">
</ListBox>
听起来你也想要一个可观察的字典,但遗憾的是框架中没有一个。你可以尝试在他的帖子"Can I bind my ItemsControl to a dictionary?"中使用Dr. Wpf的ObservableDictionary实现。
答案 1 :(得分:0)
实现可观察字典很难。维护一个包含字典值的并行可观察集合要简单得多。将视图绑定到该集合,并确保向字典添加或从字典中删除值的任何代码都会更新字典和并行集合。
如果你真的想发疯,可以实现ObservableCollection
的子类来保存你的对象,并使该类维护字典,例如:
public class KeyedObject
{
public string Key { get; set; }
public object Value { get; set; }
}
public class ObservableMappedCollection : ObservableCollection<KeyedObject>
{
private Dictionary<string, KeyedObject> _Map;
public ObservableMappedCollection(Dictionary<string, KeyedObject> map)
{
_Map = map;
}
protected override void InsertItem(int index, KeyedObject item)
{
base.InsertItem(index, item);
_Map[item.Key] = item;
}
protected override void RemoveItem(int index)
{
KeyedObject item = base[index];
base.RemoveItem(index);
_Map.Remove(item.Key);
}
protected override void ClearItems()
{
base.ClearItems();
_Map.Clear();
}
protected override void SetItem(int index, KeyedObject item)
{
KeyedObject oldItem = base[index];
_Map.Remove(oldItem.Key);
base.SetItem(index, item);
_Map[item.Key] = item;
}
}
上面有很多潜在的问题,主要是与重复键值有关。例如,如果您要添加其键已在地图中的对象,SetItem
应该做什么?答案真的取决于你的申请。这样的问题也暗示了为什么框架中没有可观察的字典类。