Reputation: 406
I've been doing some work on an app using ReactiveUI.
My issue is with UITableViews and the reusing of cells. I tried using ReactiveTableViewSource, but that didn't seem to give me the level of customisation I wanted (custom header and footer views).
So I used UITableViewSource and UITableViewCell and implemented IViewFor. I then did the binding in the individual cells.
That works fine, but I'm worried about "re-binding" to the new ViewModel every time a cell is reused. I believe I've worked around it, but I'm sure there's a better way to do it.
Code I'm using (only the relevant bit):
public partial class FlavourTableViewCell : UITableViewCell, IViewFor<MenuItemViewModel.FlavourSetItemViewModel>
{
public MenuItemViewModel.FlavourSetItemViewModel ViewModel { get; set; }
object IViewFor.ViewModel { get { return ViewModel; } set { ViewModel = (MenuItemViewModel.FlavourSetItemViewModel)value; } }
List<IDisposable> bindings = new List<IDisposable> ();
// Called when new data should be shown in cell
internal void Update (MenuItemViewModel.FlavourSetItemViewModel data, MenuItemViewModel.FlavourSelectionEnum type)
{
ViewModel = data;
// Clear old bindings
if (bindings.Any ()) {
bindings.ForEach (x => x.Dispose ());
bindings.Clear ();
}
bindings.Add (this.Bind (ViewModel, x => x.IsSelected, view => view.SelectionButton.Selected));
}
}
Additional info:
FlavourSetItemViewModel
contains a list of FlavourSetItemViewModel
. I'll try to explain below:
Upvotes: 1
Views: 433
Reputation: 194
What you're doing doesn't look wrong to me. What you could improve is using a CompositeDisposable
instead of a List of IDisposable
.
But you could also try using ReactiveTableViewSource
by using your own implementation and then overriding GetViewForHeader
to supply your own header views.
You can then bind your data to your custom table view source:
this.WhenAnyValue (view => view.ViewModel.Section1, view => view.ViewModel.Section2, (section1, section2) => new TableSectionInformation<TModel> [] {
new TableSectionInformation<TModel, TReactiveTableViewCell> (section1, "section1cell", 44),
new TableSectionInformation<TModel, TReactiveTableViewCell> (section2, "section2cell", 44)
})
.BindTo (tableViewSource, x => x.Data);
If you're using a dynamic amount of sections, you could do the following:
this.WhenAnyValue (view => view.ViewModel.TableSections)
.Select (tableData => tableData.Select (section => new TableSectionInformation<TModel, TReactiveTableViewCell> (section, "cellIdentifier", 44)).ToArray ())
.BindTo (tableViewSource, x => x.Data);
Assuming TableData
is an 2-dimensional list of sorts.
Take care that in my sample, changes to the list(s) are not taken into account. Only changes to the property (TableSections) itself.
Upvotes: 1