Observable Collection Property Changed on Item in the Collection Observable Collection Property Changed on Item in the Collection wpf wpf

Observable Collection Property Changed on Item in the Collection


Brute force:

  1. Attach handler to each PropertyChanged event for each child item
  2. Grab the ListCollectionView from your CollectionViewSource
  3. Call Refresh.

EDIT:

The code for 1, 2 would live in your code-behind.

For #1, you'd do something like:

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

For #2, in your CollectionChanged handler, you would do something like:

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

EDIT2:However, in this case, I would strongly suggest that you also check ListCollectionView.NeedsRefresh and only refresh if that is set. There's no reason to re-sort if your properties have changed which don't affect the sort.


This works. Whenever the collection changes, it re-sorts the collection. Might be doable in a more efficient way but this is the gist of it.

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>