【问题标题】:How to keep UWP UI responsive?如何保持 UWP UI 响应?
【发布时间】:2019-05-03 17:44:31
【问题描述】:

我有一个 UWP 应用程序,其中一个页面需要执行三项任务 - 首先是加载页面的主要内容(从我们的 API 检索到的“Binders”对象的集合),然后加载其他一些不依赖于第一个任务的内容。

我的页面由 ViewModel 支持(我使用默认的 Template10 MVVM 模型),当页面导航到我在 VM OnNavigatedToAsync 方法中执行此操作时:

public async override Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
{
    if (mode == NavigationMode.New || mode == NavigationMode.Refresh)
    {
        IsBusy = true;      //Show progress ring
        CreateServices();   //Create API service

        //Download binders for board and populate ObservableCollection<Binder>
        //This has a cover image and other info I want to show in the UI immediately 
        await PopulateBinders();

        //Get files and calendar events for board
        //Here I want to run this on a different thread so it does 
        //not stop UI from updating when PopulateBinders() is finished
        await Task.WhenAll(new[]
        {
            PopulateBoardFiles(),
            PopulateBoardEvents()
        });               

        IsBusy = false;
        await base.OnNavigatedToAsync(parameter, mode, state);
        return;          
    }
}

所以主要任务是PopulateBinders() - 这会调用 API,返回数据并将其加载到 Binder 的 ObservableCollection 中。当它运行时,我希望 UI 更新它的绑定并立即显示 Binder 对象,但它会等到 WhenAll 任务中的其他两个任务运行后才更新 UI。 (所有这三个任务都定义为private async Task&amp;lt;bool&amp;gt;...

我意识到我在这里遗漏了一些基本的东西 - 但我认为从异步方法调用任务会允许 UI 更新?因为它显然没有我如何重构它以使我的页面绑定在第一种方法之后更新?

我试过Task.Run(() =&gt; PopulateBinders());,但没有任何区别。

【问题讨论】:

    标签: c# mvvm uwp async-await template10


    【解决方案1】:

    我希望这段代码能帮助您按预期更新 UI:

    public async override Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
    {
        if (mode == NavigationMode.New || mode == NavigationMode.Refresh)
        {
            IsBusy = true;      //Show progress ring
            CreateServices();   //Create API service
    
            //Download binders for board and populate ObservableCollection<Binder>
            //This has a cover image and other info I want to show in the UI immediately 
            await PopulateBinders();
    
            await PouplateBoardData();
    
            await base.OnNavigatedToAsync(parameter, mode, state);
            return;          
        }
    }
    
    private async void PopulateBoardData()
    {
        await Task.WhenAll(new[]
        {
                PopulateBoardFiles(),
                PopulateBoardEvents()
        });               
    
        IsBusy = false;
    }
    

    【讨论】:

      【解决方案2】:

      不要在OnNavigatedToAsync() 中运行它,而是在页面已经加载时运行异步任务,因为你无意中“阻止”应用程序运行base.OnNavigatedToAsync() 几秒钟,直到Task.WhenAll 完成运行。

      在 MVVM 中运行加载的事件可以通过实现 Microsoft.Xaml.Interactivity 以在您的视图模型中将 Page.Loaded 事件与 DelegateCommand 类绑定来实现。

      XAML 页面(假设您使用 Prism 作为 MVVM 框架)

      <Page ...
          xmlns:core="using:Microsoft.Xaml.Interactions.Core"
          xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
          <interactivity:Interaction.Behaviors>
              <core:EventTriggerBehavior EventName="Loaded">
                  <core:InvokeCommandAction Command="{x:Bind Path=Vm.PageLoaded}" />
              </core:EventTriggerBehavior>
          </interactivity:Interaction.Behaviors>
      </Page>
      

      在您的视图模型中:

      public class PageViewModel : ... //some interface or else 
      {
          public DelegateCommand PageLoaded;
          public PageViewModel(...)
          {
               PageLoaded = new DelegateCommand(async () =>
               {
                      IsBusy = true;      
                      CreateServices();  
      
                      await PopulateBinders();
      
                      await Task.WhenAll(new[]
                      {
                          PopulateBoardFiles(),
                          PopulateBoardEvents()
                      });               
      
                      IsBusy = false;
               });
          }
      }
      

      阅读更多:Binding UWP Page Loading/ Loaded to command with MVVM

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-06
        • 2019-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-14
        • 2011-05-31
        相关资源
        最近更新 更多