AvaloniaUI/Documentation

Add documentation for binding to DynamicData observables

ewrogers opened this issue · 2 comments

From the perspective of someone who is familiar with WPF and ObservableCollection<T>, it is not immediately obvious how to use the Reactive framework for binding to Items/ItemsSource properties.

It is briefly mentioned in the Change notifications section to use DynamicData in favor of the deprecated ReactiveList (which is not even available anymore).

Going to the DynamicData repo can be quite overwhelming when your basic question is "okay... so how do I get an observable collection to bind to?"

I spent a lot of time scratching my head when exposing a variety of things like SourceList<MyViewModel>, ReadonlyObservableCollection<MyViewModel> and IObservableList<MyViewModel> and getting quite frustrated when it didn't seem observable at all!

Eventually I came to the realization that you have to do some setup work to get it to start working:

private readonly SourceList<MyViewModel> _collection = new();
private readonly ReadOnlyObservableCollection<MyViewModel> _observableCollection;

...

public ReadOnlyObservableCollection<MyViewModel> MyItems => _observableCollection;

public ICommand AddCommand { get; }
...

public MainViewModel()
{
    // Subscribe to changes to the collection
    _collection.Connect()
        .ObserveOn(RxApp.MainThreadScheduler)  // Is this necessary?
        .Bind(out _observableCollection)
        .Subscribe();

    AddCommand = ReactiveCommand.Create(() =>
    {   
        var vm = new MyViewModel();
        _collection.Add(vm);
    });
}

This may seem obvious for someone with experience with the Reactive library but for many this may be the first entry into it, like myself. I am not even sure if I am doing it "the right way" but it is indeed working.

This is something fairly common, so it would be nice to have it own documentation section for collection binding best practices.

Side note: During my frustration I went with the built-in ObservableCollection<T> but was having issues with that not actually adding items after a .Add() call. I couldn't figure out why it wasn't working with that, even when calling from the main thread. So I powered through the Rx method and finally got it working!

I would recommend looking for the original ReactiveUI/DynamicData documentation web site, as it has way more information.
Keep in mind, that ReactiveUI/DynamicData is only an optional MVVM that can be used with Avalonia, there is no reason to add more ReactiveUI/DynamicData specific pages to Avalonia documentation.

.ObserveOn(RxApp.MainThreadScheduler) // Is this necessary?

Depends. UI should be updated from the MainThread, yes. But do you need this line or not depends on which thread you call _collection.Add(vm);.
Also, some Reactive methods might redirect execution to another thread as well (like, using Delay method, which will execute code on the timer). So keeping ObserveOn is safer choice in general.

During my frustration I went with the built-in ObservableCollection but was having issues with that not actually adding items after a .Add() call

Avalonia works with build-in ObservableCollection with no issues, updating it from the main thread. Except issues in the ObservableCollection itself (like, it doesn't have Bulk operations). So, there should be another problem.