zoukankan      html  css  js  c++  java
  • DataGrid CollectionViewSource Refresh性能问题

    在WPF中,CollectionViewSource是一个经常用到的集合类型,主要用于对后台数据排序,条件筛选或分组操作。
         场景:当需要筛选包含“test”的数据项时,我们会分步输入搜索条件,依次为“t”、“te”、“tes”,而最后是“test”,而我们简单的处理经常会是在Textbox的TextChanged事件中直接添加CollectionViewSource的View的Refresh,这样筛选操作实际上进行了四次筛选操作,每一步筛选操作都会Filter及RefreshUI,对于应用来说,前几次的Filter及RefreshUI均是无用的,白白浪费了资源。
         解决方案:
         1:TextChanged中的Refresh操作进行延迟刷新,即用户输入完成后先不进行刷新,超过一定的时间再进行刷新,对于筛选条件,需要一个定时器延迟,(当筛选条件过多时,定时器数量过量,不易管理,易出错)
         2:将延迟做到CollectionViewSource中View的刷新供码中,比如,封装一个方法SourceRefresh,协定刷新_source时只能通过SourceRefresh方法。
    private CollectionViewSource _source = new CollectionViewSource();
            private DispatcherTimer timer=new DispatcherTimer();
            public void SourceRefresh()
            {
                if(timer.IsEnabled)
                    timer.Stop();
                timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
                timer.Tick += (sender, e) =>
                {
                    timer.Stop();
                    if (null != _source.View)
                        _source.View.Refresh();
                };
                timer.Start();
            }

      看源码会比较直观点,如下:

      

      下面的代码是我写的例子,可以参考下:

      

    public class MyListCollectionView<T> : ListCollectionView
        {
            public MyListCollectionView(IList list) : base(list)
            {
                _filterTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
                _filterTimer.Tick += (sender, e) =>
                {
                    CancelAllTimer();
                    RefreshFilter();
                    _freshUITimer.Start();
                    Console.WriteLine("A");
                };
                _freshUITimer.Interval = new TimeSpan(0, 0, 0, 0, 500);
                _freshUITimer.Tick += (sender, e) =>
                {
                    CancelAllTimer();
                    RefreshUI();
                    _freshCurrentTimer.Start();
                    Console.WriteLine("B");
                };
                _freshCurrentTimer.Interval = new TimeSpan(0, 0, 0, 0, 20);
                _freshCurrentTimer.Tick += (sender, e) =>
                {
                    CancelAllTimer();
                    RefreshCurrent();
                    Console.WriteLine("C");
                };
            }
    
            private DispatcherTimer _filterTimer = new DispatcherTimer();
            private DispatcherTimer _freshUITimer = new DispatcherTimer();
            private DispatcherTimer _freshCurrentTimer = new DispatcherTimer();
            private bool _isFreshFilter = false;
    
            private void CancelAllTimer()
            {
                _filterTimer.Stop();
                _freshUITimer.Stop();
                _freshCurrentTimer.Stop();
            }
    
            protected override void RefreshOverride()
            {
                _filterTimer.Start();
            }
    
            protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
            {
                if (!_isFreshFilter)
                    base.OnCollectionChanged(args);
            }
    
            protected override void OnCurrentChanged()
            {
                if (!_isFreshFilter)
                    base.OnCurrentChanged();
            }
    
            protected override void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                if (!_isFreshFilter)
                    base.OnPropertyChanged(e);
            }
    
            private void RefreshFilter()
            {
                try
                {
                    //cancel all
                    _isFreshFilter = true;
                    base.RefreshOverride();
                }
                finally
                {
                    _isFreshFilter = false;
                }
            }
    
            private void RefreshUI()
            {
                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
    
            private void RefreshCurrent()
            {
                OnCurrentChanged();
    
                OnPropertyChanged("IsCurrentAfterLast");
                OnPropertyChanged("IsCurrentBeforeFirst");
                OnPropertyChanged("CurrentPosition");
                OnPropertyChanged("CurrentItem");
            }
    
            private void OnPropertyChanged(string proName)
            {
                OnPropertyChanged(new PropertyChangedEventArgs(proName));
            }
        }
    
      public class MyCollection<T> : ObservableCollection<T>, ICollectionViewFactory
        {
            public MyCollection()
            {
            }
    
            public MyCollection(IList<T> list) : base(list)
            {
            }
    
            public MyCollection(IEnumerable<T> list) : base(list)
            {
            }
    
            public MyListCollectionView<T> _view;
    
            public ICollectionView CreateView()
            {
                _view = new MyListCollectionView<T>(this);
                return _view;
            }
        }
  • 相关阅读:
    sql 主键 标识 默认值
    SQL Server跨服务器查询
    C# 取整数
    RegisterClientScriptBlock、RegisterStartupScript
    UpdatePanel
    C#创建(从数据库中导出)Excel文件(含Interop.Excel.Dll)
    基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)
    利用JS获取IE客户端IP及MAC的实现
    Net用DataTable导出Excel通用函数(修正了Excel进程删除不掉问题)
    感人至深的文章
  • 原文地址:https://www.cnblogs.com/maigc249/p/5106749.html
Copyright © 2011-2022 走看看