2017-03-23 12 views
1

を使用して更新される次のstaticObservableCollectionがあります。なぜイベントは発砲していないのですか?静的ObservableCollectionイベントが発生していません

public static class myViewModel 
{ 

    private static ObservableCollection<ObjA> CollectionA = new ObservableCollection<ObjA>(); 
    private static ObservableCollection<ObjB> CollectionB = new ObservableCollection<ObjB>(); 

    static myViewModel() 
    { 
     CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler); 
     CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, True)); 
    } 

    private static void myHandler(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     //To do 
     throw new NotImplementedException(); 
    } 

    private static void updateCollection() 
    { 

     foreach (var x in CollectionA) 
     { 
      CollectionA.field=5; 
     } 
    } 
} 
+0

- = myHandler; '。 – Arie

答えて

3

ステップ1:CollectionAにイベントハンドラを指定します。

CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler); 

ステップ2:CollectionAを破棄し、何のハンドラを持っていない別のコレクションと交換してください。

CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true)); 

ここで行ったことを確認しますか?

CollectionAは、コレクションオブジェクトへの参照を返します。そのコレクションオブジェクトにアイテムを追加していません。そのコレクションオブジェクトを別のコレクションオブジェクトに置き換えます。

ではなく、既存のコレクションに項目を追加します。

CollectionA.CollectionChanged += new NotifyCollectionChangedEventHandler(myHandler); 

foreach (var x in CollectionB.Select(abc=> new ObjA(abc, true))) 
{ 
    CollectionA.Add(x); 
} 

あなたが本当にすべてを一度コレクションを交換したい場合は、新しいコレクションにハンドラを追加する必要があります。

CollectionA = new ObservableCollection(CollectionB.Select(abc=> new ObjA(abc, true)); 

CollectionA.CollectionChanged += myHandler; 

myHandlerに正しいパラメータと戻り値の型がある場合は、new NotifyCollectionChangedEventHandlerは必要ありません。

事のこのタイプを処理する通常の方法は、ハンドラ自体を追加CollectionAプロパティを作ることです。

private static ObservableCollection<ObjA> _collectionA; 
public static ObservableCollection<ObjA> CollectionA { 
    get { return _collectionA; } 
    set { 
     if (_collectionA != value) 
     { 
      // Remove handler from old collection, if any 
      if (_collectionA != null) 
      { 
       _collectionA.CollectionChanged -= myHandler; 
      } 

      _collectionA = value; 

      if (_collectionA != null) 
      { 
       _collectionA.CollectionChanged += myHandler; 

       // Whatever myHandler does on new items, you probably want to do 
       // that here for each item in the new collection. 
      } 
     } 
    } 
} 

static myViewModel() 
{ 
    // Now, whenever you replace CollectionA, the setter will add the changed 
    // handler automatically and you don't have to think about it. 
    CollectionA = new ObservableCollection(CollectionB.Select(abc=> new(abc, True)); 
} 

今すぐ更新

、どのようなものをことは、我々はアイテムでていますか?たぶん、そのプロパティがいつ変化するかを知りたいと思うかもしれません。 ObservableCollectionは私たちのためにそれをしませんが、私たちは自分自身の上にそれを配線することができます。

このコードをより使いやすく再利用可能な方法でリファクタリングする方法について考えるのは楽しいことです。

private static ObservableCollection<ObjA> _collectionA; 
public static ObservableCollection<ObjA> CollectionA 
{ 
    get { return _collectionA; } 
    set 
    { 
     if (_collectionA != value) 
     { 
      // Remove handler from old collection, if any 
      if (_collectionA != null) 
      { 
       _collectionA.CollectionChanged -= myHandler; 
      } 

      // 1. Remove property changed handlers from old collection items (if old collection not null) 
      // 2. Add property changed to new collection items (if new collection not null) 
      AddAndRemovePropertyChangedHandlers(_collectionA, value, ObjA_PropertyChanged); 

      _collectionA = value; 

      if (_collectionA != null) 
      { 
       _collectionA.CollectionChanged += myHandler; 
      } 
     } 
    } 
} 

// NotifyCollectionChangedEventArgs gives us non-generic IList rather than IEnumerable 
// but all we're doing is foreach, so make it as general as possible. 
protected static void AddAndRemovePropertyChangedHandlers(
    System.Collections.IEnumerable oldItems, 
    System.Collections.IEnumerable newItems, 
    PropertyChangedEventHandler handler) 
{ 
    if (oldItems != null) 
    { 
     // Some items may not implement INotifyPropertyChanged. 
     foreach (INotifyPropertyChanged oldItem in oldItems.Cast<Object>() 
      .Where(item => item is INotifyPropertyChanged)) 
     { 
      oldItem.PropertyChanged -= handler; 
     } 
    } 

    if (newItems != null) 
    { 
     foreach (INotifyPropertyChanged newItem in newItems.Cast<Object>() 
      .Where(item => item is INotifyPropertyChanged)) 
     { 
      newItem.PropertyChanged += handler; 
     } 
    } 
} 

private static void ObjA_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
} 

private static void myHandler(object sender, 
    System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
{ 
    // If e.Action is Reset, you don't get the items that were removed. Oh well. 
    AddAndRemovePropertyChangedHandlers(e.OldItems, e.NewItems, ObjA_PropertyChanged); 
} 
あなたがコレクションをchangeingアレントので、あなたもそれが
+0

はい、私はあなたがおそらく '_collectionA.CollectionChangedないはずです_collectionA''交換する前に、新しいOBJA(ABC、真) – John

+1

を意味交換しない発射いない – Default

+0

@Default私はそれを乱雑にしたくなかったが...はい、あなたは正しい。 –

関連する問題