Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 集合中项的可观察集合属性已更改_C#_Wpf_Sorting_Collections_Observablecollection - Fatal编程技术网

C# 集合中项的可观察集合属性已更改

C# 集合中项的可观察集合属性已更改,c#,wpf,sorting,collections,observablecollection,C#,Wpf,Sorting,Collections,Observablecollection,我有一个可观察的收集。我已将其绑定到ListBox控件,并已将SortDescriptions添加到ListBox上的Items集合中,以使列表按我所需的方式排序 当子元素上的任何属性发生更改时,我希望在任何点使用列表 所有我的子元素都实现了INotifyPropertyChanged暴力: 将处理程序附加到每个子项的每个PropertyChanged事件 从CollectionViewSource获取ListCollectionView 呼叫刷新 编辑: 1,2的代码将存在于您的代码背后 对于

我有一个
可观察的收集
。我已将其绑定到ListBox控件,并已将
SortDescriptions
添加到ListBox上的Items集合中,以使列表按我所需的方式排序

当子元素上的任何属性发生更改时,我希望在任何点使用列表

所有我的子元素都实现了
INotifyPropertyChanged

暴力:

  • 将处理程序附加到每个子项的每个PropertyChanged事件
  • 从CollectionViewSource获取ListCollectionView
  • 呼叫刷新
  • 编辑:

    1,2的代码将存在于您的代码背后

    对于#1,您可以执行以下操作:

    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();
    }
    
    对于#2,在CollectionChanged处理程序中,您可以执行以下操作:

    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();
    }
    
    编辑2:
    但是,在这种情况下,我强烈建议您也选中ListCollectionView.NeedsRefresh,并且仅在设置了该选项时才刷新。如果您的属性已更改,但不影响排序,则没有理由重新排序。

    此操作有效。每当集合发生更改时,它都会对集合重新排序。可能以更有效的方式可行,但这是它的要点

    
    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
        }
    
    
    公共部分类TestWindow:Window{
    可观察收集oc;
    公共测试窗口(){
    初始化组件();
    //填写OC进行测试
    oc=新的ObservableCollection();
    foreach(在“abcdefghiedjko”中的字符c){
    Add(新的TestClass(c.ToString(),c.ToString(),c.GetHashCode());
    }
    lstbox.ItemsSource=oc;
    //设置排序(这是您如何完成的..不起作用)
    lstbox.Items.SortDescriptions.Add(新的SortDescription(“A”,ListSortDirection.升序));
    //这就是我们要做的
    oc.CollectionChanged+=新系统.Collections.Specialized.NotifyCollectionChangedEventHandler(oc\U排序);
    }
    无效oc_排序(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e){
    //这将对oc进行排序并返回IEnumerable
    var项目=oc.OrderBy((x)=>(x.C));
    //Rest converst IEnumerable返回给OC并赋值
    ObservableCollection temp=新的ObservableCollection();
    foreach(项目中的var项目){
    临时添加(项目);
    }
    oc=温度;
    }
    私有无效按钮\u单击(对象发送者,路由目标e){
    字符串a=“grrrr”;
    字符串b=“ddd”;
    int c=383857;
    oc.Add(新的测试类(a、b、c));
    }
    }
    公共类TestClass:INotifyPropertyChanged{
    私人字符串a;
    私有字符串b;
    私人INTC;
    公共测试类(字符串f、字符串g、int i){
    a=f;
    b=g;
    c=i;
    }
    公共字符串A{
    获取{返回一个;}
    设置{a=value;OnPropertyChanged(“a”);}
    }
    公共字符串B{
    获取{return b;}
    设置{b=value;OnPropertyChanged(“b”);}
    }
    公共INTC{
    获取{return c;}
    设置{c=value;OnPropertyChanged(“c”);}
    }
    #已更改属性上的区域
    公共事件属性更改事件处理程序属性更改;
    受保护的无效OnPropertyChanged(字符串propertyName){
    if(this.PropertyChanged!=null){
    PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
    }
    }
    #端区
    }
    
    XAML:


    那么,您将OC绑定到一个列表框,并在列表框上有sortdescription?这是正确的。当子项的属性发生更改时,我希望排序反映此更改。此代码是否存在于我的表示层中?Window.Xaml.Cs?#1和#2的代码是什么样子的?这正是我需要的。我最后只使用了第二部分,因为在我的例子中,我有一个导致更改的事件,所以我只需要#2。ObservableCollection不侦听其元素上的PropertyChanged事件,因此当其中一个元素的属性更改时,它将无法重新排序。