How to automatically update filter and/or sort order on CollectionViewSource, when an individual item's property changes?

前端 未结 2 609
礼貌的吻别
礼貌的吻别 2021-02-14 02:24

Ok, so this question is related to Windows Phone 7/Silverlight (updated WP7 Tools, Sept 2010), specifically filtering an underlying ObservableCollection.

2条回答
  •  無奈伤痛
    2021-02-14 03:11

    I had to handle this problem and although the 'Refresh()' solution works well, it is quite long to execute because its refreshes the whole list just for one item property changed event. Not very good. And in a scenario of real time data entering the collection every 1 seconds, I let you imagine the result in user experience if you use this approach :)

    I came up with a solution which base is : when adding an item to collection wrapped in a collectionview, then the item is evaluated by the filter predicate and, based on this result, displayed or not in the view.

    So instead of calling refresh(), I came up simulating an insert of the object that got its property updated. By simulating the insert of the object, it is going to be automatically evaluated by the filter predicate without need to refresh the whole list with a refresh.

    Here is the code in order to do that :

    The derived observable collection :

    namespace dotnetexplorer.blog.com
    {
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    
    /// 
    /// Derived class used to be able to manage filter application when a collection item property changed
    ///   whithout having to do a refresh
    /// 
    internal sealed class CustomObservableCollection : ObservableCollection
    {
        /// 
        ///   Initializes a new instance of the  class.
        /// 
        public CustomObservableCollection ()
        {
        }
    
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// 
        /// The source.
        /// 
        public CustomObservableCollection (IEnumerable source)
            : base(source)
        {
        }
    
        /// 
        /// Custom Raise collection changed
        /// 
        /// 
        /// The notification action
        /// 
        public void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            OnCollectionChanged(e);
        }
    }
    }
    
    
    

    And there is the code to use when receiveing item property changed event where substitute source is a CustomObservableCollection :

            private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
    
                    // To avoid doing a refresh on a property change which would end in a very hawful user experience
                    // we simulate a replace to the collection because the filter is automatically applied in this case
                    int index = _substituteSource.IndexOf(sender);
    
                    var argsReplace = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace,
                                                                           new List { sender },
                                                                           new List { sender }, index);
                    _substituteSource.RaiseCollectionChanged(argsReplace);
                }
    
            }
        }
    
    
    

    Hope this will help !

    提交回复
    热议问题