Reputation: 704
I'm not sure what is the best method to load async data when a bound property changes.
I have a ListView and when an item is selected I display new content with a detailed data. The detail item is obtained from an async method.
Data method:
private async void ShowDetailAsync()
{
if (SelectedItem?.Id != null)
{
detailViewModel.Item = await storage.GetDetailItemAsync(SelectedItem.Id);
}
else
{
detailViewModel.Item = null;
}
}
ViewModel property:
public GearItemListViewModel SelectedItem
{
get => selectedItem;
set { this.SetValue(ref selectedItem, value); ShowDetailAsync(); }
}
Now it works as fire-and-forget async method, but how would it be the best approach to load it without risk of desynchronized view and data when user rapidly browses the records in the ListView (first click takes longer to load the record than the other)?
Or is there another method how to switch and load detail items, without async call in the property setter?
Upvotes: 2
Views: 1154
Reputation: 456437
I like to use the "asynchronous property" approach described in my MSDN article on async data binding.
In this case, your detailViewModel.Item
property would change type from TItem
to NotifyTask<TItem>
, and your ShowDetailAsync
becomes:
private void ShowDetail()
{
if (SelectedItem?.Id != null)
{
detailViewModel.Item = NotifyTask.Create(storage.GetDetailItemAsync(SelectedItem.Id);
}
else
{
detailViewModel.Item = null;
}
}
Note that the method is synchronous. It is synchronously starting an asynchronous operation.
With this change, your data binding would need to update to reference Item.Result
instead of Item
. You can then data bind to other properties such as Item.IsNotCompleted
if you want to show a spinner/loading indicator, and Item.IsFaulted
to notify the user of an error (with the previous async void
approach, any errors would be raised directly on the UI thread).
Upvotes: 4