簡體   English   中英

UI響應性並在WPF中使用“ SelectedItem” ListView / ListBox

[英]UI Responsiveness and working with “SelectedItem” ListView/ListBox in WPF

在少數情況下,我試圖設計WPF .NET 4.0應用程序以處理ListBox / ListView中SelectedItem的更改。

本質上,我想根據用戶選擇的內容查詢其他數據以填充ObservableCollection / DataGrid。 我的問題是,通過使所有內容都在同一線程上,響應性受到損害,因為在“ SelectedItem”設置程序中啟動的任何代碼完成后,被單擊的項目僅顯示為“已選擇”,並且此“等待”不響應我想要它。

通常,要查詢的數據通過LINQ從同一數據庫填充一個ObservableCollection,這就是為什么所有內容都使用同一UI線程的原因。

理想情況下,我想要:

  1. 用戶單擊列表中的一項即可立即選擇,而不會感到應用程序掛起。
  2. 要設置為true的“ IsBusy”屬性(用於綁定中,以更改某些控件的啟用狀態)。
  3. 開始查詢其他數據,然后完成查詢,應填充(例如)DataGrid,並將IsBusy返回為false。

實現“后台”輔助數據加載的最佳方法是什么? 我過去在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM