WPF中DataGrid控件的过滤(Filter)性能分析及优化
DataGrid控件是一个列表控件, 可以进行过滤,排序等。本文主要针对DataGrid的过滤功能进行分析, 并提供优化方案。
public class CustomCollectionView<T> : ListCollectionView
{
private readonly DispatcherTimer _timerRefreshCalculate = new DispatcherTimer();
private readonly DispatcherTimer _timerRefreshUI = new DispatcherTimer();
private readonly DispatcherTimer _timerRefreshCurrentItem = new DispatcherTimer();
private bool _isRefreshingCalculate = false;
private object _oldSelectedItem = null;
public CustomCollectionView(IList list)
: base(list)
{
_timerRefreshUI.Interval = new TimeSpan(0, 0, 0, 0, 300);
_timerRefreshCurrentItem.Interval = new TimeSpan(0, 0, 0, 0, 500);
_timerRefreshCalculate.Interval = new TimeSpan(0, 0, 0, 0, 200);
}
#region Override Method
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (_isRefreshingCalculate)
{
return;
}
base.OnPropertyChanged(e);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
if (_isRefreshingCalculate)
{
return;
}
base.OnCollectionChanged(args);
}
protected override void OnCurrentChanged()
{
if (_isRefreshingCalculate)
{
return;
}
base.OnCurrentChanged();
}
protected override void RefreshOverride()
{
CancelAllRefreshRequest();
StartRefresh();
}
#endregion
#region Public Method
public void CancelAllRefreshRequest()
{
_timerRefreshCurrentItem.Stop();
_timerRefreshCurrentItem.Tick -= TimerCurrentItem;
_timerRefreshUI.Stop();
_timerRefreshUI.Tick -= TimerUI;
_timerRefreshCalculate.Stop();
_timerRefreshCalculate.Tick -= TimerCalculate;
if (null != this.CurrentItem)
{
_oldSelectedItem = this.CurrentItem;
}
SetCurrent(null, -1);
}
#endregion
#region Private Method
private void StartRefresh()
{
_timerRefreshCurrentItem.Stop();
_timerRefreshCurrentItem.Tick -= TimerCurrentItem;
_timerRefreshUI.Stop();
_timerRefreshUI.Tick -= TimerUI;
_timerRefreshCalculate.Stop();
_timerRefreshCalculate.Tick -= TimerCalculate;
//begin to refresh from calculate, so set flag by true.
//and it shielded any collection action during the calculating time.
//this logic will avoid items are not correct at UI during refresh.
_isRefreshingCalculate = true;
_timerRefreshCalculate.Tick += TimerCalculate;
_timerRefreshCalculate.Start();
}
private void RefreshCalculate(CancellationToken? token)
{
_timerRefreshCalculate.Tick -= TimerCalculate;
if (null != token && null != token.Value)
{
token.Value.ThrowIfCancellationRequested();
}
_isRefreshingCalculate = true;
base.RefreshOverride();
_isRefreshingCalculate = false;
if (null != token && null != token.Value)
{
token.Value.ThrowIfCancellationRequested();
}
}
private void RefreshUI()
{
try
{
//detach timer
_timerRefreshUI.Tick -= TimerUI;
base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
//set timer to refresh current item
_timerRefreshCurrentItem.Tick -= TimerCurrentItem;
_timerRefreshCurrentItem.Tick += TimerCurrentItem;
_timerRefreshCurrentItem.Start();
}
catch (OperationCanceledException)
{
return;
}
}
private void RefreshCurrentItem()
{
_timerRefreshCurrentItem.Tick -= TimerCurrentItem;
if (null == this.InternalList || this.InternalList.Count <= 0)
{
return;
}
if (null != _oldSelectedItem)
{
var index = this.InternalList.IndexOf(_oldSelectedItem);
if (index != -1)
{
SetCurrent(_oldSelectedItem, index);
}
else
{
SetCurrent(this.InternalList[0], 0);
}
}
else
{
SetCurrent(this.InternalList[0], 0);
}
//Set event to update UI
base.OnCurrentChanged();
this.OnPropertyChanged("IsCurrentAfterLast");
this.OnPropertyChanged("IsCurrentBeforeFirst");
this.OnPropertyChanged("CurrentPosition");
this.OnPropertyChanged("CurrentItem");
}
private void TimerCalculate(object sender, EventArgs e)
{
_timerRefreshCurrentItem.Stop();
_timerRefreshCurrentItem.Tick -= TimerCurrentItem;
_timerRefreshUI.Stop();
_timerRefreshUI.Tick -= TimerUI;
try
{
RefreshCalculate(null);
}
catch (OperationCanceledException)
{
}
_timerRefreshUI.Interval = new TimeSpan(0, 0, 0, 0, 50 + Math.Min((int)(this.InternalCount / 80), 300));
_timerRefreshUI.Tick += TimerUI;
_timerRefreshUI.Start();
}
private void TimerUI(object sender, EventArgs e)
{
RefreshUI();
}
private void TimerCurrentItem(object sender, EventArgs e)
{
RefreshCurrentItem();
}
private void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class CustomCollection<T> : ObservableCollection<T>, ICollectionViewFactory
{
public CustomCollection()
{
}
public CustomCollection(List<T> list)
: base(list)
{
}
public CustomCollection(IEnumerable<T> collection)
: base(collection)
{
}
public ICollectionView CreateView()
{
return new CustomCollectionView<T>(this);
}
}
WPF中DataGrid控件的过滤(Filter)性能分析及优化的更多相关文章
- Working Experience - WPF 中 DataGrid 控件的应用
问题: 添加控件后, 编辑单元格会出现异常 绑定 ItemsSource 属性后, 更新绑定对象的数据, UI 不刷新 如何显示控件中 ComboBox 类型 解决方法: 绑定 ItemsSource ...
- WPF中DataGrid控件内Button的Command和CommandParameter的绑定
场景:视频上传功能,上传列表使用DataGrid控件,视频有不同的状态对应不同的操作,DataGrid中最后一列为操作列,里面是Button控件.希望点击Button后执行对应的操作,但是设置Butt ...
- WPF中Datagrid控件添加行号
/// <summary> /// 导入Excel文件按钮 /// </summary> /// <param name="sender">&l ...
- wpf 中DataGrid 控件的样式设置及使用
本次要实现的效果为: 这个DataGrid需要绑定一个集合对象,所以要先定义一个Experience类,包含三个字段 /// <summary> /// 定义工作经历类 /// </ ...
- WPF中查找控件的扩展类
在wpf中查找控件要用到VisualTreeHelper类,但这个类并没有按照名字查找控件的方法,于是搜索网络,整理出下面这个类,感觉用起来很是方便. 贴出来,供大家参考. /// <summa ...
- WPF的DataGrid控件从excel里复制数据然后粘贴
WPF的DataGrid控件不能像winform的DataGridView控件一样,支持值的粘贴.WPF的DataGrid控件本质上是跟数据绑定联系在一起,所以需要进行复制粘贴的操作,可以在wpf里用 ...
- WPF 4 DataGrid 控件(进阶篇一)
原文:WPF 4 DataGrid 控件(进阶篇一) 上一篇<WPF 4 DataGrid 控件(自定义样式篇)>中,我们掌握了DataGrid 列表头.行表头.行.单元格相关的 ...
- WPF 4 DataGrid 控件(进阶篇二)
原文:WPF 4 DataGrid 控件(进阶篇二) 上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...
- WPF 4 DataGrid 控件(基本功能篇)
原文:WPF 4 DataGrid 控件(基本功能篇) 提到DataGrid 不管是网页还是应用程序开发都会频繁使用.通过它我们可以灵活的在行与列间显示各种数据.本篇将详细介绍WPF 4 中 ...
随机推荐
- UVA11297 Census
题目 UVA11297 Census 做法 二维线段树,单点修改,矩阵查询,树套树(\(x,y\)),维护最大值最小值废话 有一点要注意的是:\(x\)树传到\(y\)树里面修改的时候,如果\(x\) ...
- wampserver安装在服务器中,但是mysql不能远程登录的解决方案
利用mysql workbench或者Navicat连接服务器的mysql时,有时候会出现拒绝访问, 因为在mysql中没有赋予其他用户权限,只能本地登录,所以要进行设置. 设置如下: 打开mysql ...
- python模块cgihttpserver启动
cgi是web服务器运行web应用的一种机制,web服务器通过执行cgi脚本,然后将该程序的标准输出作为http响应的一部分 CGIHTTPServer是python标准模块的web服务器,它可以运行 ...
- ssh框架整合意义
一次次学习,一次次不一样的进一步理解. 一.Struts2.String.Hibernate框架的整合的意义: 1.需要将所有的对象进行统一管理(action动作类:sessionFactory) 2 ...
- sqlserver 实时同步(发布订阅)
配置发布订阅手册 不同版本须知:https://www.sqlmanager.net/en/articles/1548 向后兼容性:参考https://docs.microsoft.com/zh-cn ...
- HDU 4004 The Frog's Games(2011年大连网络赛 D 二分+贪心)
其实这个题呢,大白书上面有经典解法 题意是青蛙要跳过长为L的河,河上有n块石头,青蛙最多只能跳m次且只能跳到石头或者对面.问你青蛙可以跳的最远距离的最小值是多大 典型的最大值最小化问题,解法就是贪心 ...
- 在eclipse中使用Github进行单元测试
时间分配是找资料60%,动手实践40%.因为之前一直没怎么好好学习,导致看到使用Gunit进行单元测试的时候感觉像是看到了一行符号一样不知所措,还好现在搜索引擎很强大,找资料学习中间有找到一个现成的傻 ...
- mapreduce job提交流程源码级分析(二)(原创)
上一小节(http://www.cnblogs.com/lxf20061900/p/3643581.html)讲到Job. submit()方法中的: info = jobClient.submitJ ...
- Explain分析查询语句
表的读取顺序 读取操作的类型 可用索引,实际使用的索引 表之间的引用 每张表多少行被优化器查询 索引的长度 EXPLAIN字段解释: ØTable:显示这一行的数据是关于哪张表的 Øpossible ...
- 阿里云分布式缓存OCS与DB之间的数据一致性
[分布式系统的数据一致性问题] OCS概要介绍 据AlertSite网络分析公司表示,Facebook的响应时间在2010年平均为1秒钟,到2011年中期已提高到了0.73秒.对比来看,响应时间占 ...