2013-03-10 3 views
0

MyClass 클래스가 포함 된 ObservableCollection이 있습니다.컬렉션의 변수가 변경된 경우 알 수 있습니다.

private ObservableCollection<MyClass> _myCollection; 

    public ObservableCollection<MyClass> MyCollection 
    { 
     get { return _myCollection; } 
     set 
     { 
      _myCollection= value; 
     } 
    } 

컬렉션이 변경된 경우 C# 코드에 대해 알고 싶습니다.

그래서 컬렉션 이벤트에 등록 : CollectionChanged 레코드를 추가/삭제할 때 작동합니다. 여기에 registred

는 :

MyCollection.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(MyCollection_CollectionChanged); 

뭔가가 클래스 내에서 변경 될 때이 이벤트가 작동 (또는 다른 이벤트 등록)하고 싶다.

처음에 나는 CollectionChanged 이벤트를 실행하여 클래스의 PropertyChanged 이벤트에 등록하려고 생각했습니다. 복잡하고 불필요한 것으로 보입니다.

wpfbinding은 클래스 자체의 변화와 컬렉션 자체의 변화를 인식 할 수 있으므로 코드를 통해이를 수행 할 수 있다고 생각합니다.

내가 틀렸어? (더 정확한 질문은 : 누구든지이 방법을 알고 있습니까?)

답변

4

이미 Nik에서 설명한 것처럼 PropertyChanged 이벤트는 올바른 방법입니다. 하지만 당신은 수동으로 CollectionChanged 이벤트를 호출해서는 안된다고 생각합니다.

public class MyClass : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value; OnPropertyChanged("Name"); } 
    } 

    private void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class Class1 
{ 
    private ObservableCollection<MyClass> _myCollection = new ObservableCollection<MyClass>(); 
    public ObservableCollection<MyClass> MyCollection 
    { 
     get { return _myCollection; } 
     // set { _myCollection = value; } // see Clemens' comment 
    } 

    public Class1() 
    { 
     // hook up this event at the appropriate place, does not have to be the ctor 
     MyCollection.CollectionChanged += MyCollection_CollectionChanged; 

     MyClass m = new MyClass() { Name = "Example" }; 

     MyCollection.Add(m); // calls ExecuteOnAnyChangeOfCollection 
     m.Name = "ChangedValue"; // calls ExecuteOnAnyChangeOfCollection 
    } 

    void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.NewItems != null) 
     { 
      foreach (MyClass item in e.NewItems) 
       item.PropertyChanged += MyClass_PropertyChanged; 
     } 

     if (e.OldItems != null) 
     { 
      foreach (MyClass item in e.OldItems) 
       item.PropertyChanged -= MyClass_PropertyChanged; 
     } 

     ExecuteOnAnyChangeOfCollection(); 
    } 

    void MyClass_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     ExecuteOnAnyChangeOfCollection(); 
    } 

    private void ExecuteOnAnyChangeOfCollection() 
    { 
     // handling code ... 
     System.Windows.MessageBox.Show("Collection has changed."); 
    } 
+1

+1을, 그러나 당신은'MyCollection' 속성 setter에서'MyCollection_CollectionChanged' 처리기를 추가/제거 할 것입니다 : 당신은이 같은 이벤트 내부에 코드를 리팩토링해야한다. – Clemens

+0

@Clemens : 당신이 말하는 것을 볼 수 있습니다. 그렇게하지 않으면 감지하기 힘든 추악한 문제가 발생할 수 있습니다 (클래스 외부에서 MyCollection이 설정되고 이벤트가 더 이상 실행되지 않음). 유스 케이스? 예를 들어, 초기 데이터로드는'ExecuteOnAnyChangeOfCollection'을 유발하지 않을 수도 있습니다. 나는 속성을 읽기 전용으로 만들 것입니다. 토론이 질문의 범위를 벗어난 경우에도 힌트 (+1)에 감사드립니다. –

+0

변경 사항을 UI에 표시하려면 항목의 속성 변경에 대해 CollectionChanged 이벤트를 호출해야합니다. 그리고 보통은 –

2

당신 말이 맞습니다. MyClass에서 알림을 얻는 가장 쉬운 방법은 PropertyChanged 이벤트를 구독하는 것입니다 (MyClass가 INotifyPropertyChanged를 구현하는 경우).

UI를 업데이트하려면 변경된 항목 제거 및 추가 (이 작업은 CollectionChanged가 자동으로 증가 함) 또는 재설정 매개 변수가있는 CollectionChanged 이벤트를 수동으로 호출 할 수 있습니다 (ObservableCollection 클래스를 확장해야 할 필요가 있지만 매우 쉽습니다). 태스크).