利用WPF的ListView進行大數據量異步加載


     由於之前利用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中用了匿名方法來實現,非常方便。

 源代碼下載:點擊這里下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM