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.
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.