C# 实现CollectionChanged
我已将C# 实现CollectionChanged,c#,wpf,mvvm,mvvm-light,C#,Wpf,Mvvm,Mvvm Light,我已将CollectionChanged事件处理程序(onCollectionChanged)添加到observeableCollection属性之一 我发现,onCollectionChanged方法仅在向集合添加项或删除项的情况下调用,而在编辑集合项的情况下不调用 我想知道如何在单个集合中发送新添加、删除和编辑项目的列表/集合 谢谢。我认为在ObservableCollection中填充实现INotifyPropertyChanged的项将导致CollectionChanged事件在项发出其
CollectionChanged事件处理程序(onCollectionChanged)
添加到observeableCollection
属性之一
我发现,onCollectionChanged
方法仅在向集合添加项或删除项的情况下调用,而在编辑集合项的情况下不调用
我想知道如何在单个集合中发送新添加、删除和编辑项目的列表/集合
谢谢。我认为在ObservableCollection
中填充实现INotifyPropertyChanged
的项将导致CollectionChanged
事件在项发出其PropertyChanged
通知时触发
再想一想,我认为您需要使用BindingList
以这种开箱即用的方式传播单个项的更改
否则,您需要手动订阅每个项目的更改通知,并引发
CollectionChanged
事件。请注意,如果您要创建自己的派生的observeCollection
,则必须在实例化时以及在Add()
和Insert()
上订阅,并在Remove()
和Clear()
上取消订阅。否则,您可以订阅CollectionChanged
事件,并使用事件参数中添加和删除的项来订阅/取消订阅。在winforms中,BindingList
是标准做法。在WPF&Silverlight中,您通常无法使用ObservableCollection
,需要监听每个项目上的PropertyChanged
INotifyCollectionChanged
与InotifyPropertyChanged
不相同。更改基础对象的属性并不表示集合已更改
实现此行为的一种方法是创建一个自定义集合,该集合在添加对象后将进行查询,并注册INotifyPropertyChanged.PropertyChanged
事件;当一个项目被移除时,它将需要适当地取消注册
这种方法的一个警告是,当对象嵌套在N层深时。为了解决这个问题,您需要使用反射来检查每个属性,以确定它是否是另一个实现INotifyCollectionChanged
的集合,或者是需要遍历的其他容器
这是一个未经测试的基本示例
public class ObservableCollectionExt<T> : ObservableCollection<T>
{
public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
protected override void SetItem(int index, T item)
{
base.SetItem(index, item);
if(item is INotifyPropertyChanged)
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
}
protected override void ClearItems()
{
for (int i = 0; i < this.Items.Count; i++)
DeRegisterINotifyPropertyChanged(this.IndexOf(this.Items[i]));
base.ClearItems();
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
RegisterINotifyPropertyChanged(item);
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
DeRegisterINotifyPropertyChanged(index);
}
private void RegisterINotifyPropertyChanged(T item)
{
if (item is INotifyPropertyChanged)
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(OnPropertyChanged);
}
private void DeRegisterINotifyPropertyChanged(int index)
{
if (this.Items[index] is INotifyPropertyChanged)
(this.Items[index] as INotifyPropertyChanged).PropertyChanged -= OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
T item = (T)sender;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, item));
}
}
公共类ObservableCollectionExt:ObservableCollection
{
公共覆盖事件System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
受保护的覆盖无效集合项(整数索引,T项)
{
base.SetItem(索引,项);
如果(项目为INotifyPropertyChanged)
(项目作为INotifyPropertyChanged)。PropertyChanged+=新PropertyChangedEventHandler(OnPropertyChanged);
}
受保护的覆盖无效ClearItems()
{
for(int i=0;i
您必须为每个项目添加一个PropertyChanged
侦听器(必须实现INotifyPropertyChanged
),以获取有关编辑可观察列表中对象的通知
public ObservableCollection<Item> Names { get; set; }
public List<Item> ModifiedItems { get; set; }
public ViewModel()
{
this.ModifiedItems = new List<Item>();
this.Names = new ObservableCollection<Item>();
this.Names.CollectionChanged += this.OnCollectionChanged;
}
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach(Item newItem in e.NewItems)
{
ModifiedItems.Add(newItem);
//Add listener for each item on PropertyChanged event
newItem.PropertyChanged += this.OnItemPropertyChanged;
}
}
if (e.OldItems != null)
{
foreach(Item oldItem in e.OldItems)
{
ModifiedItems.Add(oldItem);
oldItem.PropertyChanged -= this.OnItemPropertyChanged;
}
}
}
void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
Item item = sender as Item;
if(item != null)
ModifiedItems.Add(item);
}
publicobservableCollection名称{get;set;}
公共列表ModifiedItems{get;set;}
公共视图模型()
{
this.ModifiedItems=新列表();
this.Names=新的ObservableCollection();
this.Names.CollectionChanged+=this.OnCollectionChanged;
}
CollectionChanged无效(对象发送方,NotifyCollectionChangedEventArgs e)
{
如果(如NewItems!=null)
{
foreach(e.NewItems中的Item newItem)
{
ModifiedItems.Add(新建项);
//为PropertyChanged事件上的每个项目添加侦听器
newItem.PropertyChanged+=此.OnItemPropertyChanged;
}
}
如果(例如,OldItems!=null)
{
foreach(e.OldItems中的项目oldItem)
{
修改后的项目。添加(旧项目);
oldItem.PropertyChanged-=此.OnItemPropertyChanged;
}
}
}
void OnItemPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
项目=发送方作为项目;
如果(项!=null)
修改项目。添加(项目);
}
也许您必须检查某个项目是否已经在ModifiedItems列表中(列表的方法包含(object obj)),并且仅当该方法的结果为false时才添加新项目
类项
必须实现INotifyPropertyChanged
。看看这个,知道怎么做。正如Robert Rossney所说,如果您有此要求,您也可以使用IEditableObject
。一个项目
public class IceCream: INotifyPropertyChanged
{
private int liczba;
public int Liczba
{
get { return liczba; }
set { liczba = value;
Zmiana("Liczba");
}
}
public IceCream(){}
//in the same class implement the below-it will be responsible for track a changes
public event PropertyChangedEventHandler PropertyChanged;
private void Zmiana(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
async private void Add_Click(object sender, RoutedEventArgs e)
{
List<IceCream> items = new List<IceCream>();
foreach (IceCream item in IceCreamList.SelectedItems)
{
int i=Flavors.IndexOf(item);
Flavors[i].Liczba =item.Liczba+ 1;
//Flavors.Remove(item);
//item.Liczba += 1;
// items.Add(item);
// Flavors.Add(item);
}
MessageDialog d = new MessageDialog("Zwiększono liczbę o jeden");
d.Content = "Zwiększono liczbę o jeden";
await d.ShowAsync();
IceCreamList.SelectedIndex = -1;
}
}
private ObservableCollection<IceCream> Flavors;
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach(Item newItem in e.NewItems)
{
ModifiedItems.Add(newItem);
//Add listener for each item on PropertyChanged event
if (e.Action == NotifyCollectionChangedAction.Add)
newItem.PropertyChanged += this.ListTagInfo_PropertyChanged;
else if (e.Action == NotifyCollectionChangedAction.Remove)
newItem.PropertyChanged -= this.ListTagInfo_PropertyChanged;
}
}
// MSDN: OldItems:Gets the list of items affected by a Replace, Remove, or Move action.
//if (e.OldItems != null) <--- removed
}