2012-06-19 86 views
0

我有一個列表控件,每個控件有zIndex屬性:如何創建的ObservableCollection通過項目的屬性排序和發射CollectionChanged當項目的屬性更改

class WizardControl : INotifyPropertyChanged 
{ 
    public int ZIndex { get; set; /* set emits PropertyChanged event */} 
} 

class WizardStep 
{ 
    ObservableCollection<WizardControl> Controls { get; set; } 
} 

class Wizard 
{ 
    ObservableCollection<WizardStep> Steps { get; set; } 
} 

我也有一個TreeView使用HierarchicalDataTemplate,每個WizardStep哪裏所有WizardControl都有一個樹節點作爲樹葉。

現在我想按照它們的ZIndex對控件進行排序。我發現了一個使用自定義Converter(http://stackoverflow.com/a/5730402/69868)的解決方案,只要ZIndex沒有改變,它就可以正常工作。

當ZIndex更改時,已排序的CollectionView不會發出CollectionChanged事件,GUI也不會選擇更改順序。

我的問題:如何創建一個排序的集合,當由於排序值的改變而重新排序項目時將發出正確的事件?

回答

0

爲此,您必須使用CollectionView環繞您的​​ObservableCollectionCollectionView.SortDescriptions.Add(new SortDescription(ZIndex))

這樣,只要observable集合中任何項目的ZIndex發生更改,它就會自動在GUI上獲取正確的排序位置。

+0

我做到了,並且GUI沒有拿起zIndex的變化。 –

+0

它的奇怪! ...這對我來說很有用......你確定你正在提升setter中的'PropertyChanged'事件嗎? –

0

我想你可以在一個集合中自己實現INotifyCollectionChanged接口,該集合可以偵聽WizardControl的屬性已更改事件參數,從而完全控制事情的完成。我已經包含了一個如何完成的小例子。

WizardControl.cs

public class WizardControl : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     int zIndex; 
     PropertyChangedEventArgs zIndexArgs = new PropertyChangedEventArgs("ZIndex"); 

     public int ZIndex 
     { 
      get { return zIndex; } 
      set 
      { 
       if (zIndex != value) 
       { 
        zIndex = value; 
        PropertyChangedEventHandler temp = PropertyChanged; 
        if (temp != null) 
         temp(this, zIndexArgs); 
       } 
      } 
     } 

     public override string ToString() 
     { 
      return zIndex.ToString();  

     } 
} 

WizardCollection.cs

public class WizardCollection : INotifyCollectionChanged, IEnumerable<WizardControl> 
{ 
    public event NotifyCollectionChangedEventHandler CollectionChanged; 
    NotifyCollectionChangedEventArgs collectionChangedMoveArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset); 

    List<WizardControl> items = new List<WizardControl>(); 

    public WizardControl this[int index] 
    { 
     get { return items[index]; } 
    } 

    public void Add(WizardControl item) 
    { 
     if (items == null) items = new List<WizardControl>(); 
     items.Add(item); 
     item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged); 
     NotifyCollectionChangedEventHandler temp = CollectionChanged; 
     if (temp != null) 
      temp(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); 
    } 

    public void Remove(WizardControl item) 
    { 
     item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged); 
     NotifyCollectionChangedEventHandler temp = CollectionChanged; 
     if (temp != null) 
      temp(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); 
    } 

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "ZIndex") 
     { 
      items = items.OrderBy(x => x.ZIndex).ToList(); 
      NotifyCollectionChangedEventHandler temp = CollectionChanged; 
      if (temp != null) 
       temp(this, collectionChangedMoveArgs); 
     } 
    } 

    public IEnumerator<WizardControl> GetEnumerator() 
    { 
     return items.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return items.GetEnumerator(); 
    } 
} 
0

ObservableCollection只提出了一個PropertyChange通知時,收集的變化,而不是在集合變化中的對象。

如果你想要這種行爲,你必須自己添加它。通常我將它添加到CollectionChanged事件中。

public MyViewModel() 
{ 
    MyCollection.CollectionChanged += MyCollection_CollectionChanged; 
} 

void MyCollection_CollectionChanged(object sender, CollectionChangedEventArgs e) 
{ 
    if (e.NewItems != null) 
     foreach(MyItem item in e.NewItems) 
      item.PropertyChanged += MyItem_PropertyChanged; 

    if (e.OldItems != null) 
     foreach(MyItem item in e.OldItems) 
      item.PropertyChanged -= MyItem_PropertyChanged; 
} 

void MyItem_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "Some Property") 
    { 
     // Do work 
     RaisePropertyChanged("MyCollection"); 
    } 
} 

由於您使用的是集合A轉換器僅僅是提高了徵收PropertyChanged事件應努力重新運行轉換器

相關問題