2009-06-18 34 views
11

Tôi có một số ObservableCollection<T>. Tôi đã bị ràng buộc nó vào một ListBox kiểm soát và tôi đã thêm SortDescriptions vào bộ sưu tập Items trên ListBox để làm cho danh sách sắp xếp theo cách tôi muốn.Thuộc tính sưu tập có thể quan sát được thay đổi trên mục trong bộ sưu tập

Tôi muốn sử dụng danh sách tại ANY điểm khi bất kỳ thuộc tính nào được thay đổi trên phần tử con.

Tất cả các phần tử con của tôi thực hiện INotifyPropertyChanged.

+0

Vì vậy, bạn đang ràng buộc OC của bạn vào một Listbox và có sortdescription trên listbox? – apandit

+0

Đúng vậy. Khi một thuộc tính của một mục con được thay đổi, tôi muốn loại phản ánh thay đổi này. – Nate

Trả lời

12

lực lượng Brute:

  1. Đính kèm handler cho mỗi sự kiện PropertyChanged cho mỗi mục con
  2. Grab các ListCollectionView từ CollectionViewSource bạn
  3. Gọi Refresh.

EDIT:

mã cho 1, 2 sẽ sống trong bạn code-behind.

Đối # 1, bạn muốn làm điều gì đó như:

private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    switch (e.Action) 
    { 
     case NotifyCollectionChangedAction.Add: 
      foreach(SomeItem item in e.NewItems) 
      { 
       item.PropertyChanged += new PropertyChangedEventHandler(_SomeItem_PropertyChanged); 
      } 
      break; 
.... 
**HANDLE OTHER CASES HERE** 
.... 
     } 
} 

Đối # 2, trong handler CollectionChanged bạn, bạn sẽ làm điều gì đó như:

private void _SomeItem_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(theListBox.ItemsSource)); 
    lcv.Refresh(); 
} 

EDIT2: Tuy nhiên, trong trường hợp này, tôi sẽ mạnh mẽ đề nghị bạn cũng kiểm tra ListCollectionView.NeedsRefresh và chỉ làm mới nếu được đặt. Không có lý do gì để sắp xếp lại nếu các thuộc tính của bạn đã thay đổi mà không ảnh hưởng đến sắp xếp.

+0

Mã này có tồn tại trong tầng trình bày của tôi không? Window.Xaml.Cs? Mã số cho # 1 và # 2 trông như thế nào? – Nate

+0

Đó chính xác là những gì tôi cần. Tôi đã kết thúc chỉ bằng cách sử dụng phần thứ hai, vì trong trường hợp của tôi tôi có một sự kiện gây ra sự thay đổi, vì vậy tôi chỉ cần # 2. – Nate

0

Tác phẩm này. Bất cứ khi nào bộ sưu tập thay đổi, nó sẽ sắp xếp lại bộ sưu tập. Có thể làm được một cách hiệu quả hơn nhưng đây là ý chính của nó.

 

public partial class TestWindow : Window { 
     ObservableCollection<TestClass> oc; 
     public TestWindow() { 
      InitializeComponent(); 
      // Fill in the OC for testing 
      oc = new ObservableCollection<TestClass>(); 
      foreach(char c in "abcdefghieeddjko") { 
       oc.Add(new TestClass(c.ToString(), c.ToString(), c.GetHashCode())); 
      } 

      lstbox.ItemsSource = oc; 
      // Set up the sorting (this is how you did it.. doesn't work) 
      lstbox.Items.SortDescriptions.Add(new SortDescription("A", ListSortDirection.Ascending)); 
      // This is how we're going to do it 
      oc.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(oc_Sort); 
     } 

     void oc_Sort(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { 
      // This sorts the oc and returns IEnumerable 
      var items = oc.OrderBy<TestClass, int>((x) => (x.C)); 
      // Rest converst IEnumerable back to OC and assigns it 
      ObservableCollection<TestClass> temp = new ObservableCollection<TestClass>(); 
      foreach(var item in items) { 
       temp.Add(item); 
      } 
      oc = temp; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) { 
      string a = "grrrr"; 
      string b = "ddddd"; 
      int c = 383857; 
      oc.Add(new TestClass(a, b, c)); 
     } 


    } 

    public class TestClass : INotifyPropertyChanged { 
     private string a; 
     private string b; 
     private int c; 

     public TestClass(string f, string g, int i) { 
      a = f; 
      b = g; 
      c = i; 
     } 
     public string A { 
      get { return a; } 
      set { a = value; OnPropertyChanged("A"); } 
     } 
     public string B { 
      get { return b; } 
      set { b = value; OnPropertyChanged("B"); } 
     } 
     public int C { 
      get { return c; } 
      set { c = value; OnPropertyChanged("C"); } 
     } 

     #region onpropertychanged 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void OnPropertyChanged(string propertyName) { 
      if(this.PropertyChanged != null) { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
     #endregion 
    } 
 

XAML:

 
<Window x:Class="ServiceManager.TestWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="TestWindow" Height="500" Width="500"> 
    <DockPanel> 
     <ListBox ItemsSource="{Binding}" x:Name="lstbox"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <Label Content="{Binding Path=A}"/> 
         <Label Content="{Binding Path=B}"/> 
         <Label Content="{Binding Path=C}"/> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
     <Button Click="Button_Click" Content="Click" /> 
    </DockPanel> 
</Window> 
+2

ObservableCollection không lắng nghe các sự kiện PropertyChanged trên các yếu tố của nó, do đó, điều này sẽ không tái sắp xếp khi một thuộc tính của một trong các yếu tố được thay đổi. http://msdn.microsoft.com/en-us/magazine/dd252944.aspx – Odrade

Các vấn đề liên quan