Правильный способ привязать команду к кнопке внутри ячейки таблицы в MvvmCross - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь настроить таблицу элементов (UITableView) с кнопкой в ​​каждой ячейке, которая ведет к подробному профилю ее элемента.

Но я не уверен, каков правильный подход кэто в MvvmCross.Вот некоторые из моих идей:

  • Представьте выход кнопки ItemCellView как общедоступный и свяжите его внутри GetOrCreateCellFor
  • Передайте ShowItemDetailsCommand в каждый ItemCellView и связайтеэто там
  • Используйте простой обратный вызов от ItemCellView до ItemsView вместо привязки
  • Получите отдельный MvxViewModel для каждой ячейки и оттуда вызовите службу навигации
public class Item
{
    public string Name { get; set; }
}
public class ItemsViewModel : MvxViewModel
{
    public List<Item> Items { get; }
    public MvxCommand ShowItemDetailsCommand { get; }

    readonly IMvxNavigationService _navigationService;
    readonly IDatabaseService _databaseService;

    public ItemsViewModel(IMvxNavigationService navigationService, IDatabaseService databaseService)
    {
        ShowItemDetailsCommand = new MvxCommand(ShowItemDetails);

        _navigationService = navigationService;
        _databaseService = databaseService;

        Items = _databaseService.SelectItems();
    }

    void ShowItemDetails()
    {
        // not sure how "item" gets here so far
        _navigationService.Navigate<ItemDetailsViewModel, Item>(item);
    }
}
public partial class ItemsView : MvxTableViewController<ItemsViewModel>
{
    public ItemsView() : base("ItemsView", null) {}

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        TableView = View as UITableView;

        var source = new TableViewSource(TableView);
        var bindings = this.CreateBindingSet<ItemsView, ItemsViewModel>();
        bindings.Bind(source).To(vm => vm.Items);
        bindings.Apply();

        TableView.Source = source;
        TableView.ReloadData();
    }

    public class TableViewSource : MvxTableViewSource
    {
        public TableViewSource(UITableView tableView) : base(tableView)
        {
            TableView.RegisterNibForCellReuse(UINib.FromName("ItemCellView", NSBundle.MainBundle), ItemCellView.kCellId);
        }

        protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
        {
            return TableView.DequeueReusableCell(ItemCellView.kCellId, indexPath) as ItemCellView;
        }
    }
}
public partial class ItemCellView : MvxTableViewCell
{
    public const string kCellId = "item_cell";
    // also has an [Outlet] UIButton in the .designer.cs part

    public ItemCellView(IntPtr handle) : base(handle)
    {
        this.DelayBind(() =>
        {
            var bindings = this.CreateBindingSet<ItemCellView, Item>();
            bindings.Bind(Name).To(i => i.Name);
            bindings.Apply();
        });
    }
}

1 Ответ

0 голосов
/ 23 мая 2018

Вы должны привязать кнопку ItemCellView в методе построения вашей ячейки:

// MyBtn is my Cell's button outlet
protected ItemCellView(IntPtr handle) : base(handle)
{
    this.DelayBind(() =>
    {
        var bindings = this.CreateBindingSet<MyTableViewCell, Item>();

        // Use this bind to set your button's title
        bindings.Bind(MyBtn).For("Title").To(item => item.Name);

        // This bind is used for binding a command in the Item model
        // CommandParameter can pass your parameter
        bindings.Bind(MyBtn).To(item => item.ShowItemDetailsCommand).CommandParameter(DataContext);

        bindings.Apply();
    });
}

Поскольку в ячейке DataContext был изменен на вашу модель Item, необходимо настроить команду привязкив классе модели:

public class Item
{
    private readonly Lazy<IMvxNavigationService> _navigationService = new Lazy<IMvxNavigationService>(Mvx.Resolve<IMvxNavigationService>);

    public string Name { set; get; }

    private ICommand showItemDetailsCommand;
    public ICommand ShowItemDetailsCommand
    {
        get
        {
            return showItemDetailsCommand ?? (showItemDetailsCommand = new MvxCommand<Item>(ShowItemDetails));
        }
    }
    async void ShowItemDetails(Item item)
    {
        await _navigationService.Value.Navigate<SecondViewModel, Item>(item);
    }
}

Наконец The SecondViewModel, которую вы хотите нажать, получит этот параметр через событие Prepare():

public class SecondViewModel : MvxViewModel<Item>
{
    public override void Prepare(Item parameter)
    {

    }
}
...