Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现CollectionChanged_C#_Wpf_Mvvm_Mvvm Light - Fatal编程技术网

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
}