zoukankan      html  css  js  c++  java
  • (转)利用WPF的ListView进行大数据量异步加载

    原文:http://www.cnblogs.com/scy251147/archive/2012/01/08/2305319.html

    由于之前利用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);
    tsStatus.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
    {
    tsStatus.Content = "正在加载中。。。";
    }));
    }

    /// <summary>
    /// 对BindData函数进行异步处理完毕,向用户发送通知
    /// </summary>
    /// <param name="iar"></param>
    private void EndBindData(IAsyncResult iar)
    {
    tsStatus.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
    {
    tsStatus.Content = "加载完毕。。。";
    }));
    BindDataAsync bindData = (BindDataAsync)iar.AsyncState;
    bindData.EndInvoke(iar);
    }

    /// <summary>
    /// 考虑到BindData导入数据比较耗时,采用了BeginBindData来进行异步加载
    /// </summary>
    private void BindData()
    {

    GetHeader();
    DataTable dt = LoadData();

    tsStatus.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方法,在代码中,是这样做到的(拿名称为tsStatus的Label控件来说):

     tsStatus.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate
    {
    tsStatus.Content = "当前已经加载"+count+"条数据。。。";
    }));

     

    在Action中用了匿名方法来实现,非常方便。

  • 相关阅读:
    Android 模拟系统事件(三)
    全民Scheme(2):来自星星的你
    Java经典23种设计模式之行为型模式(三)
    libmysqld,嵌入式MySQLserver库
    闲云控制台(一)控制台命令解析框架
    怎样改动android系统字体大小
    [多校2015.02.1006 高斯消元] hdu 5305 Friends
    换工作经历和心得
    安卓实训第七天---多线程下载实现(进度条)
    校园双选会,你都懂么
  • 原文地址:https://www.cnblogs.com/hhhh2010/p/8675893.html
Copyright © 2011-2022 走看看