読者です 読者をやめる 読者になる 読者になる

Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

ObservableCollectionの中身が変更されたことを検知する方法

c#のDataBindingで必ずと言っていいほど使われる、ObservableCollectionというやつ。

こいつはコレクション自体の変更を検知する仕組みはあるけど、そのコレクションに格納されているオブジェクトの変更までは検知されない。色々とStackOverFlowとかStackOverFlowを見て雰囲気をつかみ、最終的にこのような形にしてみた。

行を追加するときにPropertyChangedをリッスンするのは、追加された時にPropetyChangedイベントハンドラが空のため。削除するときにイベントを消しているのは、消さないと古いアイテムにリッスンしっぱなしのイベントが発行されるため。たぶんのこの理解であってる。

値の変更時には、古いアイテムのイベントを消して新しくなったオブジェクトにイベントを付与している。削除からの追加って感じでイベントを再登録している。

もちろん、ObservableCollectionに格納されるModelにもINotifyPropertyChangedを実装することを忘れないこと!

using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections.ObjectModel;
//ViewModelBaseではINotifyPropertyChangedを実装
 public class OrderEntryViewModel : ViewModelBase
 {
        private ObservableCollection<OrderDetailModel> _orderlist;

        public OrderEntryViewModel()
        {
            _orderlist = new ObservableCollection<OrderDetailModel>();
            _orderlist.CollectionChanged += _orderlist_CollectionChanged;
        }
        void _orderlist_CollectionChanged(object sender,        System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Replace)
            {
                foreach (OrderDetailModel item in e.OldItems)
                    item.PropertyChanged -= MyType_PropertyChanged;
                foreach (OrderDetailModel item in e.NewItems)
                    item.PropertyChanged += MyType_PropertyChanged;
            }
            else if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (OrderDetailModel item in e.NewItems)
                    item.PropertyChanged += MyType_PropertyChanged;
            }
            else if (e.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (OrderDetailModel item in e.OldItems)
                    item.PropertyChanged -= MyType_PropertyChanged;
            }
        
        }
 void MyType_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
                //change event hook here
         }
 }