首页 > 解决方案 > ObervableCollection、CollectionChanged 和 PropertyChanged

问题描述

几天来,我一直在试图弄清楚如何解决我的问题。

我有一个类似的数据结构(我使用 PropertyChanged.Fody 库):

public class Item1 : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     public int Somma { get => this.Lista.Sum(o => o.Valore);}
     public ObservableCollection<Item2> Lista {get; set;}
     /*Other fields*/
}

public class Item2 : INotifyPropertyChanged
{
     public event PropertyChangedEventHandler PropertyChanged;

     public int Valore {get; set;}
     /*Other fields*/
}

在我的视图中,我有两个类似的 ListView(lista 是 Item1 的 ObservableCollection):

<mr:ListView x:Name="listView1" ItemsSource="{Binding lista}" SelectedItem="{Binding listView1Selected, Mode=TwoWay}">
    <mr:ListView.ItemTemplate>
        <DataTemplate>
            <mr:ViewCell>
                <StackLayout Orientation="Horizontal">
                    <Label Text="{Binding Somma}" TextColor="Black" />
                </StackLayout>
            </mr:ViewCell>
        </DataTemplate>
    </mr:ListView.ItemTemplate>
</mr:ListView>
<mr:ListView x:Name="listView2" ItemsSource="{Binding listView1Selected.Lista}" SelectedItem="{Binding listView2Selected, Mode=TwoWay}">
    <mr:ListView.ItemTemplate>
        <DataTemplate>
            <mr:ViewCell>
                <StackLayout Orientation="Vertical" >
                    <Label Text="{Binding Valore}" TextColor="Black" />
                </StackLayout>
            </mr:ViewCell>
        </DataTemplate>
    </mr:ListView.ItemTemplate>
</mr:ListView>

当我在 ViewModel.cs 中调用更改某些 Item2 的字段 Valore 的值时,我希望重新计算 Item1 的总和并自动绑定。我尝试将 ObservableCollection 替换为如下类:

public class ItemsChangeObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged
    {       
        public ItemsChangeObservableCollection() : base()
        {            
        }

        public ItemsChangeObservableCollection(IEnumerable<T> list) : base(list)
        {            
            RegisterPropertyChanged(list.ToList());            
        }

        public ItemsChangeObservableCollection(List<T> list): base(list)
        {            
            RegisterPropertyChanged(list);
        }  
     
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                RegisterPropertyChanged(e.NewItems);
            }
            else if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                UnRegisterPropertyChanged(e.OldItems);
            }
            else if (e.Action == NotifyCollectionChangedAction.Replace)
            {
                UnRegisterPropertyChanged(e.OldItems);
                RegisterPropertyChanged(e.NewItems);
            }

            base.OnCollectionChanged(e);            
        }

        protected override void ClearItems()
        {
            UnRegisterPropertyChanged(this);
            base.ClearItems();
        }

        private void RegisterPropertyChanged(IList items)
        {
            foreach (INotifyPropertyChanged item in items)
            {
                if (item != null)
                {
                    item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
                }
            }
        }

        private void UnRegisterPropertyChanged(IList items)
        {
            foreach (INotifyPropertyChanged item in items)
            {
                if (item != null)
                {
                    item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
                }
            }
        }

        private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }       
    }

但它仍然不起作用。谁能帮帮我吗?

编辑

使用 ItemsChangeObservableCollection 类,我可以在更新 Valore 字段时进入他的方法 item_PropertyChanged。所以我希望调用

base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));

一个 CollectionChanged 它是生成的......但它不是。如果我添加 Item1 构造函数,例如

public Item1()
{
    Lista= new ItemsChangeObservableCollection<Item2>();
    Lista.CollectionChanged += MyCollectionChanged;     
}

MyCollectionChanged 永远不会被解雇。为什么????

标签: c#xamarinobservablecollectioninotifypropertychangedinotifycollectionchanged

解决方案


我意识到出了什么问题。当我在我的视图模型中实例化列表时,我试图在 Item1 构造函数中添加的 CollectionChanged hadler 被覆盖。

在我的视图模型中初始化后添加 CollectionChanged 可以解决问题。


推荐阅读