MVVMCross iOS: How to trigger RowSelected on a Custom TableViewSource using CreateBindingSet?

mvvm, mvvmcross, xamarin, xamarin.ios

Solution

You can bind a view model command to the `SelectionChangedCommand` on the table source.

This technique is demonstrated in several samples - e.g

- N=27 http://www.youtube.com/watch?v=h0Eww89c9DM&feature=youtu.be&t=47m30s

https://github.com/slodge/MvvmCross-Tutorials/tree/master/DailyDilbert

// command
new Cirrious.MvvmCross.ViewModels.MvxCommand<DilbertItem>((dilbertItem) => 
{
   // note that we can only pass an id here - do *not* serialiase the whole dilbertItem
   ShowViewModel<DilbertDetailViewModel>(new { id = dilbertItem.Id });
});

// binding
set.Bind(source)
   .For(s => s.SelectionChangedCommand)
   .To(s => s.ShowDetailCommand);

Alternatively, you can also put commands inside your list items and can then bind within each cell to a `SelectedCommand` (or some other custom event within your cell).

For examples of this, look at some of the samples which have menus - e.g. the ValueConversion sample

Problem

My question is for MVVMCross in iOS. I have a custom TableView and a detailView. How can I bind my "showDetailCommand", so when user click on one of the rows on TableView with trigger RowSelected to switch to detailViewModel? Here is my code structure: ``` public class SearchResultsViewModel: MvxViewModel { private MvxCommand _showDetailCommand; public IMvxCommand ShowDetailCommand { get { _showDetailCommand = _showDetailCommand ?? new MvxCommand(ShowDetailCommandHandler); return _showMapCommand; } } private void ShowDetailCommandHandler() { ShowViewModel<ResultDetailViewModel>(new { city = _filter.City, state = _filter.State, interstate = _filter.Interstate, travelPlaza = _filter.SearchTravelPlaza, hasCatScale = _filter.HasCatScale, hasWashoutExpress = _filter.HasWashoutExpress, hasUndercarriage = _filter.HasUndercarriage, nearest = _nearest }); } } [Register("SearchResults")] public class SearchResultsView : MvxTableViewController { public override void ViewDidLoad() { Title = "List"; base.ViewDidLoad(); var source = new TableViewSource(TableView); var bindings = this.CreateBindingSet<SearchResultsView, SearchResultsViewModel>(); bindings.Bind(source).To(vm => vm.Items); bindings.Apply(); TableView.BackgroundColor = UIColor.Clear; TableView.ShowsVerticalScrollIndicator = false; TableView.ScrollEnabled = true; TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None; TableView.Source = source; TableView.ReloadData(); } public class TableViewSource : MvxTableViewSource { public TableViewSource(UITableView tableView) : base(tableView) { tableView.RegisterClassForCellReuse(typeof(TableViewCell), TableViewCell.CellIdentifier); } public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath) { var item = GetItemAt(indexPath); return TableViewCell.CellHeight(item); } protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item) { var cell = tableView.DequeueReusableCell(TableViewCell.CellIdentifier) ?? new TableViewCell(); return cell; } } } [Register("TableViewCell")] public class TableViewCell : MvxTableViewCell { public static readonly NSString CellIdentifier = new NSString("TableViewCell"); public TableViewCell() : base() { Initialise(); } public TableViewCell(IntPtr handle) : base(handle) { Initialise(); } private void Initialise() { var titleLabel = new UILabel(new RectangleF(10, 2, 200, 25)); Add(titleLabel); this.DelayBind(() => { var bindings = this.CreateBindingSet<TableViewCell, SearchResultsItemViewModel>(); bindings.Bind(titleLabel).For(x => x.Text).To(vm => vm.Name); bindings.Bind(??).For(x => x.SelectionChangeCommand).To(vm => vm.showDetailCommand); // what should be in this line ?? bindings.Apply(); }); } } ```

Original source