Skip to content
Michal Diviš edited this page Dec 2, 2019 · 1 revision

How to use it?

Create the collection

Create a collection of type AsyncObservableCollection<T> somewhere in your code (your view model, for example).

public class MainViewModel
{
    public AsyncObservableCollection<string> Items { get; set; } = new AsyncObservableCollection<string>();
}

Initialize the collection

Before using it, you need to initialize the collection from each platform specific project. In my example, I have a WPF .NET Framework project and a Xamarin.Forms .NET Standard project. I'll initialize the collections for my view model from each platform, before I start using the view model.

The collection implements the IAsyncObservableCollection interface, so you can find all of them with reflection (see the InitAsyncCollectionsAutomatically method) or initialize them manually (see the InitAsyncCollections method).

WPF project

I have this method in the view (WPF Window) that is associated with the view model. It get's called from the constructor of the view.

public MainWindow()
{
    InitializeComponent();

    _model = new MainViewModel();
    this.DataContext = _model;

    //call the initialize method for async collections
    InitAsyncCollectionsAutomatically(_model);
}

/// <summary>
/// Initializes all properties that implement the IAsyncObservableCollection interface
/// </summary>
/// <param name="model">The object, that holds the collections</param>
private void InitAsyncCollectionsAutomatically(object model)
{
    //select all properties that implement IAsyncObservableCollection
    var collections = model.GetType().GetProperties()
    .Where(a => typeof(IAsyncObservableCollection).IsAssignableFrom(a.PropertyType))
    .Select(a => a.GetValue(model) as IAsyncObservableCollection);
    
    //initialize them all
    InitAsyncCollections(collections);
}

/// <summary>
/// Initializes an enumerable of IAsyncObservableCollection
/// </summary>
/// <param name="collections">The collections that need to be initialized</param>
private void InitAsyncCollections(IEnumerable<IAsyncObservableCollection> collections)
{
    foreach (var collection in collections)
    {
        //initialize the collection
        collection.Init(action => Dispatcher?.Invoke(() => action?.Invoke()));
    }
}

Xamarin.Forms project

And the exact same methods (with a Xamarin.Forms dispatcher) is in my view (Xamarin.Forms ContentPage), and it get's called from the constructor of the view, as well.

public MainPage()
{
    InitializeComponent();

    _model = new MainViewModel();
    this.BindingContext = _model;

    //call the initialize method for async collections
    InitAsyncCollectionsAutomatically(_model);
}

/// <summary>
/// Initializes all properties that implement the IAsyncObservableCollection interface
/// </summary>
/// <param name="model">The object, that holds the collections</param>
private void InitAsyncCollectionsAutomatically(object model)
{
    //select all properties that implement IAsyncObservableCollection
    var collections = model.GetType().GetProperties()
    .Where(a => typeof(IAsyncObservableCollection).IsAssignableFrom(a.PropertyType))
    .Select(a => a.GetValue(model) as IAsyncObservableCollection);

    //initialize them all
    InitAsyncCollections(collections);
}

/// <summary>
/// Initializes an enumerable of IAsyncObservableCollection
/// </summary>
/// <param name="collections">The collections that need to be initialized</param>
private void InitAsyncCollections(IEnumerable<IAsyncObservableCollection> collections)
{
    foreach (var collection in collections)
    {
        //initialize the collection
        collection.Init(action => Device.BeginInvokeOnMainThread(() => action?.Invoke()));
    }
}

And now, use it

Now you can do things like this, freely.

await Task.Run(() =>
{
    Items.Clear();
    Items.Add("Item 1");     
    Items.AddRange(new []
    {
        "Item 2", 
        "Item 3", 
    });         
});