Observable Collection Property Changed on Item in the Collection 在集合中的项目上,可观察集合属性已更改

9 浏览
0 Comments

Observable Collection Property Changed on Item in the Collection 在集合中的项目上,可观察集合属性已更改

我有一个ObservableCollection。我将它绑定到一个ListBox控件,并在ListBox的Items集合上添加了SortDescriptions,以便按我想要的方式对列表进行排序。当任何子元素的属性发生更改时,我想在任何时候重新排序列表。所有的子元素都实现了INotifyPropertyChanged。

0
0 Comments

ObservableCollection无法监听其元素的PropertyChanged事件,因此当元素的属性更改时,无法重新对集合进行排序。要解决这个问题,可以通过在TestClass类中实现INotifyPropertyChanged接口,并在属性的setter方法中调用OnPropertyChanged方法来解决。此外,还需要在oc_Sort方法中重新创建一个新的ObservableCollection对象,并将排序后的元素重新添加到新的集合中。

以下是修改后的代码:

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
            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 convert 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>

问题的原因是ObservableCollection无法监听其元素的PropertyChanged事件,解决方法是在TestClass类中实现INotifyPropertyChanged接口,并在属性的setter方法中调用OnPropertyChanged方法来通知属性更改。另外,需要在oc_Sort方法中重新创建一个新的ObservableCollection对象,并将排序后的元素重新添加到新的集合中。这样在集合元素属性更改时,集合会重新排序。

0
0 Comments

Observable Collection Property Changed on Item in the Collection

当在集合中的项上发生Observable Collection属性更改时,可能会出现问题。下面是解决该问题的原因和方法。

问题原因:

Observable Collection是一个特殊的集合类型,当其中的项发生更改时,它会自动通知订阅者。然而,当集合中的项的属性发生更改时,Observable Collection本身并不会触发属性更改事件。这意味着,如果我们希望在集合中的项的属性更改时接收通知,我们需要手动处理。

解决方法:

以下是一种解决方法,通过在每个子项上附加PropertyChanged事件处理程序来实现:

1. 为每个子项的PropertyChanged事件附加处理程序。

2. 从CollectionViewSource中获取ListCollectionView。

3. 调用Refresh方法。

代码示例:

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
    }
}
private void _SomeItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    ListCollectionView lcv = (ListCollectionView)(CollectionViewSource.GetDefaultView(theListBox.ItemsSource));
    lcv.Refresh();
}

在此示例中,Source_CollectionChanged方法用于处理Observable Collection的CollectionChanged事件。在该方法中,我们检查了事件的类型,如果是添加操作,我们遍历新添加的项并为每个项的PropertyChanged事件附加处理程序。

_SomeItem_PropertyChanged方法是PropertyChanged事件的处理程序。在该方法中,我们获取ListCollectionView并调用Refresh方法,以便刷新视图。

在解决此问题时,可以选择仅在ListCollectionView.NeedsRefresh设置为true时刷新视图,以避免不必要的排序操作。

这些代码可以放在窗口的代码后台中(Window.Xaml.Cs)。

以上就是解决Observable Collection Property Changed on Item in the Collection问题的原因和方法。

0