I have a UWP app in which one of the pages needs to do three tasks - the first is to load the main content for the page (a collection of 'Binders' objects retrieved from our API) then after that load some other content which are not dependent on the first task in any way.
My page is backed with a ViewModel (I'm using the default Template10 MVVM model) and when the page is navigated to I do this in the VM OnNavigatedToAsync method:
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;
}
}
So the main task is PopulateBinders() - this calls the API, returns the data and loads it into an ObservableCollection of Binder. When this has run I want the UI to update it's bindings and show the Binder objects immediately but instead it waits until the two other tasks in the WhenAll Task) have run before updating the UI. (All three of these Tasks are defined as private async Task<bool>...)
I realise I'm missing something basic here - but I thought calling a Task from an async method would allow the UI to update? Since it clearly doesn't how do I refactor this to make my page bindings update after the first method?
I tried Task.Run(() => PopulateBinders()); but it made no difference.
I hope this code will help you to update the UI as expected: