Unplanned
Last Updated: 29 Nov 2022 08:17 by AscanioTziazas
AscanioTziazas
Created on: 29 Nov 2022 08:17
Category: ListView
Type: Feature Request
1
ListView: LoadOnDemandCollection should accept an asynchronous callback returning a Task

Currently the LoadOnDemandCollection accepts a callback of the following format in the constructor:

public LoadOnDemandCollection(Func<CancellationToken, IEnumerable> action)

It is a very common scenario to populate the items asynchronously. In its current form the collection would require blocking the current thread to populate the results:

ItemsSource = new ListViewLoadOnDemandCollection((cancelationToken) =>
{
    var result = new List<ItemsModel>();
    try
    {
        var items = dataService.GetItemsAsync().Result;

        // TODO: Handle the result.

        return result;
    }
    catch (Exception e)
    {
        // TODO: Handle the exception.
        return null;
    }
});

This is not desired, as using Task.Result blocks the current thread and is considered an anti-pattern, in general.

A better approach would be to add a second overload of the constructor, allowing asynchronous calls:

public LoadOnDemandCollection(Func<CancellationToken, Task<IEnumerable>> action)

This way we can use async and await in the callback instead:

ItemsSource = new ListViewLoadOnDemandCollection(async (cancelationToken) =>
{
    var result = new List<ItemsModel>();
    try
    {
        var items = await dataService.GetItemsAsync();

        // TODO: Handle the result.

        return result;
    }
    catch (Exception e)
    {
        // TODO: Handle the exception.
        return null;
    }
});

According to my tests, the first blocking approach is not a problem, as the ListViewLoadOnDemandCollection starts a thread internally. That behavior is not obvious however, and using Task.Result is somewhat counterintuitive, so the second approach is much better from the user's perspective.

0 comments