[英]UI Responsiveness and working with “SelectedItem” ListView/ListBox in WPF
在少數情況下,我試圖設計WPF .NET 4.0應用程序以處理ListBox / ListView中SelectedItem的更改。
本質上,我想根據用戶選擇的內容查詢其他數據以填充ObservableCollection / DataGrid。 我的問題是,通過使所有內容都在同一線程上,響應性受到損害,因為在“ SelectedItem”設置程序中啟動的任何代碼完成后,被單擊的項目僅顯示為“已選擇”,並且此“等待”不響應我想要它。
通常,要查詢的數據通過LINQ從同一數據庫填充一個ObservableCollection,這就是為什么所有內容都使用同一UI線程的原因。
理想情況下,我想要:
實現“后台”輔助數據加載的最佳方法是什么? 我過去在WinForms中使用過BackgroundWorker,但是渴望了解有關Dispatcher的更多信息,我認為這是正確的方向。
我的SelectedItem屬性很簡單:
public Employee SelectedEmployee
{
get
{
return mvSelectedEmployee;
}
set
{
mvSelectedEmployee = value;
RaisePropertyChanged();
IsBusy = true;
QueryMyEmployeesAddressesAndOtherData(); //which takes sometimes 2 seconds
IsBusy = false;
}
}
我希望用戶知道有什么事情在發生,但盡管有些延遲,但還是很流暢。
謝謝。
使用異步/等待是實現此目的的最佳方法。 您的特定情況的一個問題是,屬性設置器不能標記為async
。 但是,您可以從設置器中觸發async void
方法。 這是一個簡單的示例,無需您在代碼庫中進行任何其他更改即可使用:
public Employee SelectedEmployee
{
get
{
return mvSelectedEmployee;
}
set
{
mvSelectedEmployee = value;
RaisePropertyChanged();
UpdateSelectedEmployeeAsync();
}
}
private async void UpdateSelectedEmployeeAsync()
{
IsBusy = true;
await Task.Run(() => QueryMyEmployeesAddressesAndOtherData());
IsBusy = false;
}
但是,您可能真正想做的是使QueryMyEmployeesAddressesAndOtherData
異步到“一路下行”。 Task.Run
實際上更適合在后台運行受CPU約束的操作,但是聽起來您的任務可能主要是受IO約束的(等待一些查詢執行)。 無論您使用哪種持久性框架,都極有可能支持異步(如果不支持,請考慮更新為可以支持的異步框架)。 現在,您可能會得到如下結果:
private async void UpdateSelectedEmployeeAsync()
{
IsBusy = true;
await QueryMyEmployeesAddressesAndOtherDataAsync();
IsBusy = false;
}
private async Task QueryMyEmployeesAddressesAndOtherDataAsync()
{
using (var ctx = new MyContext())
{
var queryResults = await ctx.EmployeeData.Where(t=>t.EmployeeId == SelectedEmployee.Id).ToArrayAsync();
SelectedEmployeeDatas.Clear();
foreach (var data in queryResults)
{
SelectedEmployeeDatas.Add(data);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.