2013-07-04 53 views
1

我想提出一個自定義集合是基於關閉列表中集合對象的變化,其目的是要觀察的,防止重複,排序等如何觀看的自定義集合內

我有一個add方法一樣所以:

public class SortedObservableCollection<T> : List<T>, INotifyPropertyChanged, INotifyCollectionChanged 
    { 
     public void Add(T item) 
     { 
      base.Add(item); 
      base.Sort(); 
      this.OnPropertyChanged("Count"); 
      this.OnPropertyChanged("Item[]"); 
      this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item); 
     } 
} 

但不知何故,當對象是直接收集內改變,我需要一個自動度假區發生,或在收集得到通知,因此可以再次這樣做排序。

像:

SortedObservableCollection<IRCUser> users = new SortedObservableCollection<IRCUser>(); 
users.Add(new IRCUser { Nick = "User1", Status = IRCUserStatus.Unknown }); 
users.Add(new IRCUser { Nick = "User2", Status = IRCUserStatus.Unknown }); 
users.Add(new IRCUser { Nick = "User3", Status = IRCUserStatus.Unknown }); 


users.Single(x => x.Nick == "User3").Nick = "User11"; 

用戶3停留在收集的底部,請注意我用我自己的IComparable的實施,它不只是一個字母排序。

我需要集合來捕捉這個變化並通知我,所以我可以做點什麼。

我知道我將要落實的對象INotifyPropertyChanged的,但我不能確定的是如何將採集聽清楚,我可以看到的唯一方法是,如果在add方法我做的:

item.PropertyChanged += (o,e) { ..check then... base.Sort(); }; 

但是,如果我有10,000個用戶,這是要走的路嗎?

回答

0

項目類必須實現INotifyPropertyChanged 那麼你有兩個選擇: 保存在子類(項)列表(父)和項目的propertyChange你打電話或當你添加一定的方法

項目添加到您的列表中NotifyPropertyChanged事件。我會這樣。

列表:

public listclass() 
{ 
    this.ListChanged += new ListChangedEventHandler(listclass_ListChanged); 
}  

void listclass_ListChanged(object sender, ListChangedEventArgs e) 
{ 
    if (e.ListChangedType == ListChangedType.ItemAdded) 
    { 
    item item = this[e.NewIndex]; 
    item.PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged); 
    } 
} 

void Item_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "propertyname") 
    { 

    }  
} 

項目實現INotifyPropertyChanged:

public item() 
{  
    this.PropertyChanged += new PropertyChangedEventHandler(AnyPropertyChanged); 
} 

private void AnyPropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    // example how to use 
    if (e.PropertyName == "anyproperyname") 
    { 

    } 
} 

public event PropertyChangedEventHandler PropertyChanged; 
public void InvokePropertyChanged(PropertyChangedEventArgs e) 
{ 
    PropertyChangedEventHandler handler = PropertyChanged; 
    if (handler != null) handler(this, e); 
} 

private Boolean bTheProperty = true; 
public Boolean TheProperty 
{ 
    get { return bTheProperty ; } 
    set 
    { 
    if (bTheProperty != value) 
    { 
     bTheProperty = value; 
     InvokePropertyChanged(new PropertyChangedEventArgs("TheProperty")); 
    }   
    } 
} 

一些列表中,您必須將此屬性設置爲true,所以它觸發了ListChanged事件:

this.RaiseListChangedEvents = true; 

如果你不想使用屬性改變的事件,你可以去這種骯髒的方式:

private list oParent 

public item(list parent) 
{ 
    this.oParent = parent; 
} 

private string sName; 
public string Name 
{ 
    get { return sName; } 
    set 
    { 
    if (sName!= value) 
    { 
     sName= value; 
     if(this.parent != null) 
     { 
     this.parent.IsSorted = false; 
     } 
    }   
    } 
} 

然後你可以在列表類中使用一個計時器並檢查isSorted是否爲false,或者調用list.IsSorted屬性中的一個propertychanged。

+0

我想你基本上正在實現我在想什麼(列表中每個對象的處理程序)。 – sprocket12

+0

是的,只需要做一個BindingList Koryu

0

正如我以爲似乎解決方案是將偵聽器添加到集合中的每個對象,並刪除它時刪除項目。我可以實現像這樣:

public class SortedObservableList<T> : List<T>, INotifyPropertyChanged, INotifyCollectionChanged where T : INotifyPropertyChanged, IComparable<T> 
{ 
    public void Add(T item) 
    { 
     base.Add(item); 
     base.Sort(); 
     this.OnPropertyChanged("Count"); 
     this.OnPropertyChanged("Item[]"); 
     this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item); 
     item.PropertyChanged += InnerObjectChanged; 
    } 

    private void InnerObjectChanged(object sender, PropertyChangedEventArgs e) 
    { 
     base.Sort(); 
    } 

    public bool Remove(T item) 
    { 
     item.PropertyChanged -= InnerObjectChanged; 
     bool result = base.Remove(item); 
     this.OnPropertyChanged("Count"); 
     this.OnPropertyChanged("Item[]"); 
     this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item); 
     return result; 
    } 

    protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = "") 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, object item) 
    { 
     if (this.CollectionChanged != null) 
     { 
      this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
} 

IRCUser

public class IRCUser : IComparable<IRCUser>, INotifyPropertyChanged 
    { 
     private string _nick; 
     public string Nick 
     { 
      get 
      { 
       return _nick; 
      } 
      set 
      { 
       if (value != _nick) 
       { 
        ... 
        OnPropertyChanged(); 
       } 
      } 
     } 

     public int CompareTo(IRCUser other) 
     { 
... 
     } 


     private void OnPropertyChanged([CallerMemberName] String propertyName = "") 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 

我剛纔測試了這一點,似乎工作。