由于之前利用Winform的ListView进行大数据量加载的时候,诟病良多,所以今天试着用WPF的ListView来做了一下,结果没有让我失望,我将一个拥有43000行,510列的csv文件导入到了ListView中,总共耗时在10s左右,并且在导入的过程中,软件界面上的提示信息一直在提示当前导入了多少条。在整个导入的过程中没有感觉到ListView的闪烁。
在测试大数据量加载的时候,我们有两件事情需要完成,第一个就是考虑到大数据量,我们得利用异步方式来进行,否则界面及其容易被阻塞住;第二个就是由于数据量过大,导入时间可能比较长,如何通知用户当前导入的进度。
针对问题一,可以考虑利用委托的异步方式进行;针对问题二,可以考虑到线程和UI交互的方式。
首先要说的是大数据量的导入,和WinForm不同的是,在导入数据到ListView之前,我们需要先将数据导入到一个DataTable中,然后利用GridView来处理DataTable,最后绑定即可,见代码流程:
/// <summary> /// 开始对BindData函数进行异步处理 /// </summary> private void BeginBindData() { ........ } /// <summary> /// 对BindData函数进行异步处理完毕,向用户发送通知 /// </summary> /// <param name="iar"></param> private void EndBindData(IAsyncResult iar) { ........ } /// <summary> /// 考虑到BindData导入数据比较耗时,采用了BeginBindData来进行异步加载 /// </summary> private void BindData() { ........ } 这就是整个异步加载方式的执行流程,下面见具体代码: #region Invoke the Binding Data method asynchorously /// <summary> /// 开始对BindData函数进行异步处理 /// </summary> private void BeginBindData() { BindDataAsync bindData = new BindDataAsync(BindData); IAsyncResult iar = bindData.BeginInvoke(new AsyncCallback(EndBindData), bindData); label.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { label.Content = "正在加载中。。。"; })); } /// <summary> /// 对BindData函数进行异步处理完毕,向用户发送通知 /// </summary> /// <param name="iar"></param> private void EndBindData(IAsyncResult iar) { label.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { label.Content = "加载完毕。。。"; })); BindDataAsync bindData = (BindDataAsync)iar.AsyncState; bindData.EndInvoke(iar); } /// <summary> /// 考虑到BindData导入数据比较耗时,采用了BeginBindData来进行异步加载 /// </summary> private void BindData() { GetHeader(); DataTable dt = LoadData(); label.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { tsStatus.Content = "正在绑定数据,请稍候。。。"; })); //using Dispatcher to avoid crossing thread exception listView1.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate { foreach (DataColumn item in dt.Columns) { GridViewColumn gvc = new GridViewColumn(); //设置行的绑定源 gvc.DisplayMemberBinding = new Binding(item.ColumnName); //设置头部名称 gvc.Header = item.ColumnName; gv.Columns.Add(gvc); } //设置显示方式,利用GridView来显示 listView1.View = gv; //设置待绑定的上下文数据对象 listView1.DataContext = dt; //绑定数据,不可缺少,否则导致绑定失败 listView1.SetBinding(ListView.ItemsSourceProperty, new Binding()); })); } #endregion
关于如何向用户发送通知,这个涉及到了线程和UI交互,在Winform中我们可以通过Control.InvokeRequired来判断是否需要进行交互,然后通过Invoke方法进行进一步处理,而在WPF中,则需要利用Dispacther来进行处理,也即:Control.Dispacter方法,在代码中,是这样做到的(拿名称为label的Label控件来说):
label.Dispatcher.Invoke(DispatcherPriority.Normal,new Action(delegate { label.Content = "当前已经加载"+count+"条数据。。。"; }));
这篇文档对您是否有帮助?