3

Apologies if the terminology is off; I'm an iOS developer having to use Xamarin.iOS to develop an app. I'm using ReactiveUI with DynamicData and an MVVM architecture. I'm fairly happy with RxSwift, and FRP concepts in general. I have a Model that publishes a SourceList<MyThing>, according to the docs, like so:

// Property declarations
private readonly SourceList<MyThing> Things;
public IObservableCollection<MyThing> ThingsBindable { get; }

// Later, in the constructor...
Things = new SourceList<MyThing>();
// Is this of the right type?
ThingsBindable = new ObservableCollectionExtended<MyThing>();
Things
    .Connect()
    .Bind(ThingsBindable)
    .Subscribe();

I can successfully use .BindTo() in my View (i.e. ViewController in iOS-land) to get a UITableView to update when the Model changes:

Model
    .WhenAnyValue(model => model.ThingsBindable)
    .BindTo<MyThing, MyThingTableViewCell>(
        tableView,
        new NSString("ThingCellIdentifier"),
        46, // Cell height
        cell => cell.Initialize());  

I'd like, instead of binding directly to the Model, to have the ViewModel subscribe-and-publish (or otherwise proxy) the SourceList<MyThing>, or the bindable version of this, so that the View is only using the ViewModel properties. The SourceList is declared private in the docs; I'm unsure of best practice here: do I make it public and do my Connect() in the ViewModel? Or is there a way of passing on the publicly exposed IObservableCollection<MyThing> ThingsBindable from the ViewModel? I'm also not convinced that ObservableCollectionExtended<MyThing> is the right type for the Bindable property, but it seems to work.

I've tried various combinations of .ToProperty(), .Bind(), .Publish() etc. and making a version of the View-binding Observable in the ViewModel to no avail and am now just throwing autocomplete at the wall to see what sticks. Any direction appreciated. TIA.

Robin Macharg
  • 1,468
  • 14
  • 22
  • Usually ReadOnlyObservableCollection is the type you use for Bind() except on winforms where you need binding list support. Usually also SourceList is made private since it shouldn't be used in your View. You can expose the Connect() method and the `IObservable>` it produces. – Glenn Watson Mar 13 '19 at 00:02

1 Answers1

5

I think it was beginners misunderstanding. Here's what I've got working the way I want; maybe it will help other Xamarin.iOS/ReactiveUI/DynamicData newbies.

In my model I declare both a private SourceList and a publicly exposed IObservableList<MyThing>:

private readonly SourceList<MyThing> _ModelThings;
public IObservableList<MyThing> ModelThings;

Then instantiate them in my constructor:

_ModelThings = new SourceList<MyThing>();
ModelThings = _Things.AsObservableList();

In my ViewModel I declare a local ObservableCollectionExtended<MyThing> and bind that to the Model's public property:

public ObservableCollectionExtended<MyThing> ViewModelThings;

// Then, in the constructor:
ViewModelThings = new ObservableCollectionExtended<MyThing>();

model.ModelThings
    .Connect()
    .Bind(ViewModelThings)
    .Subscribe();

In my ViewController I bind the table to the ViewModel.ViewModelThings, as in the question. If I wanted to have another level of Model I could simply pass through the Model.ModelThings and .Connect().Bind() lower down, as Glenn hinted in his comment.

FWIW, I found Roland's Blog (specifically the sections on Observable Lists/Caches) to be more straightforward to understand than the GitHub docs.

Robin Macharg
  • 1,468
  • 14
  • 22
  • Out of curiosity have you seen the documentation we wrote for RxUI and DynamicData? https://reactiveui.net/docs/handbook/collections/ – Glenn Watson Mar 13 '19 at 09:47
  • I have! And must have read it about 30 times. But what I couldn't see yesterday was the `SourceList.AsObservableList()` used together. There's `ObservableCollection.AsObservableList()` and `SourceList.Connect()` near the top but not my specific use case. Rereading it now, it makes sense, and I can see my pieces expressed lower down the page. But for a non-MS Rx (iOS) developer there's a lot of building blocks to try and assemble in my head and map over from similar concepts (Like LINQ provides map(), but calls it select(). Who knew?) Getting there! – Robin Macharg Mar 13 '19 at 12:57
  • 1
    I was about to answer this one and I see it has already been answered. I agree with everything said – Roland Pheasant Mar 13 '19 at 20:43
  • I too have read the docs many times; especially the [collections/DynamicData](https://www.reactiveui.net/docs/handbook/collections/#converting-reactivelist-to-dynamicdata) section. I can find how I'm recommended NOT to proceed, but am struggling to see HOW to proceed. A newbie to this kind of coding; I'll keep on keeping on – Neil Gatenby Dec 23 '21 at 15:16