2009-06-18 40 views
11

Tengo un ObservableCollection<T>. Lo he vinculado a un control ListBox y he agregado SortDescriptions a la colección Items en el ListBox para hacer que la lista ordene cómo quiero.Observable Colección propiedad modificada en el elemento en la colección

Quiero recurrir a la lista en CUALQUIER punto cuando cualquier propiedad ha cambiado en un elemento secundario.

Todos mis elementos secundarios implementan INotifyPropertyChanged.

+0

es así, estás de unión a su OC a un cuadro de lista y tienen la sortdescription en el cuadro de lista? – apandit

+0

Eso es correcto. Cuando se cambia una propiedad de un elemento secundario, me gustaría que el género refleje este cambio. – Nate

Respuesta

12

fuerza bruta:

  1. Acople manejador de cada evento PropertyChanged para cada elemento secundario
  2. Coge la ListCollectionView de su CollectionViewSource
  3. llamada Actualizar.

EDIT:

El código de 1, 2 viviría en el código subyacente.

Para # 1, que haría algo como:

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** 
.... 
     } 
} 

Para # 2, en el controlador CollectionChanged, que haría algo como:

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

Edit2: Sin embargo, en En este caso, quisiera fuertemente sugiero que también marque ListCollectionView.NeedsRefresh y solo actualice si está configurado. No hay ninguna razón para volver a ordenar si sus propiedades han cambiado, lo que no afecta el género.

+0

¿Viviría este código en mi nivel de presentación? Window.Xaml.Cs? ¿Cómo se verían los códigos de # 1 y # 2? – Nate

+0

Eso es exactamente lo que necesitaba. Terminé usando solo la segunda parte, ya que en mi caso tengo un evento que está causando el cambio, así que solo necesitaba el número 2. – Nate

0

Esto funciona. Cada vez que la colección cambia, vuelve a ordenar la colección. Podría ser posible de una manera más eficiente, pero esta es la esencia de la misma.

 

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 no escucha los eventos PropertyChanged en sus elementos, por lo que no se volverá a ordenar cuando se cambie una propiedad de uno de los elementos. http://msdn.microsoft.com/en-us/magazine/dd252944.aspx – Odrade

Cuestiones relacionadas