【问题标题】:ObervableCollection, CollectionChanged and PropertyChangedObervableCollection、CollectionChanged 和 PropertyChanged
【发布时间】:2021-08-16 15:18:47
【问题描述】:

这几天我一直在想办法解决我的问题。

我有一个类似这样的数据结构(我使用 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));
        }       
    }

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

编辑

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

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

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

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

MyCollectionChanged 永远不会被触发。为什么????

【问题讨论】:

  • 请参阅 Fody 文档中的“依赖属性” - github.com/Fody/PropertyChanged#notes
  • “从属属性”段落中描述的行为仅对同一类的字段有效,对子对象字段无效。
  • 作为一个选项,您可以在Item2 类中拥有一个属性Item1 Owner,并在Valore 设置器中提升Owner.PropertyChanged
  • mmmm 好的,这是一个想法......但是还有其他一些解决方案可以让我的数据结构保持不变吗?已经够复杂了!我会正确使用 ItemsChangeObservableCollection 类,就像我在 EDITED 帖子中写的那样

标签: c# xamarin observablecollection inotifypropertychanged inotifycollectionchanged


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 2011-12-23
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 2011-06-03
    • 2011-06-03
    相关资源
    最近更新 更多