MvxItemTemplate ItemClick 绑定

MvxItemTemplate ItemClick Binding

我在 MvxListView 上有以下绑定

        <Mvx.MvxListView
            android:id="@+id/listGroups"
            android:layout_height="fill_parent"
            android:layout_width="fill_parent"
            android:layout_below="@+id/layoutGroupPadder"
            android:dividerHeight="7dp"
            android:divider="@drawable/list_divider"
            local:MvxItemTemplate="@layout/list_group"
            local:MvxBind="ItemsSource AvailableGroups; ItemClick GroupSelectedCommand" />

MvxItemTemplate如下

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/xxxx.xxxx"
    android:orientation="horizontal"
    android:background="@color/white"
    android:layout_width="fill_parent"
    android:layout_height="63dp">
    <TextView
        android:id="@+id/groupsGroupName"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:textSize="18dp"
        android:gravity="center"
        android:layout_margin="7dp"
        android:textColor="@color/verydarknavy"
        local:MvxBind="Text Name" />
    <RelativeLayout
        android:id="@+id/layoutGroupGroupCount"
        android:orientation="horizontal"
        android:layout_width="90dp"
        android:layout_height="fill_parent"
        android:layout_centerInParent="true">
        <TextView
            android:id="@+id/groupsSubGroupCount"
            android:layout_width="50dp"
            android:layout_height="fill_parent"
            android:textSize="16dp"
            android:gravity="center"
            android:layout_margin="7dp"
            android:textColor="@color/hblue"
            android:layout_toLeftOf="@+id/imageArrowGrp"
            local:MvxBind="Text SubGroupCount" />
        <ImageView
            android:src="@drawable/YellowArrowRight"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_margin="7dp"
            android:layout_alignParentRight="true"
            android:id="@+id/imageArrowGrp" />
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/layoutGroupItemCount"
        android:orientation="horizontal"
        android:layout_width="90dp"
        android:layout_height="fill_parent"
        android:layout_marginRight="14dp"
        android:layout_alignParentRight="true"
        android:fitsSystemWindows="false">
        <TextView
            android:id="@+id/groupsVehicleCount"
            android:layout_width="50dp"
            android:layout_height="fill_parent"
            android:textSize="16dp"
            android:gravity="center"
            android:layout_margin="7dp"
            android:textColor="@color/hblue"
            android:layout_toLeftOf="@+id/imageArrowItem"
            local:MvxBind="Text VehicleCount" />
        <ImageView
            android:src="@drawable/YellowArrowRight"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_margin="7dp"
            android:id="@+id/imageArrowItem" />
    </RelativeLayout>
</RelativeLayout>

当发生 ItemClick 时,GroupSelectedCommand 会正确触发:)

但是我想根据用户在项目中触摸的位置触发 2 个不同的命令。我需要区分触摸了哪些 TexView(SubGroupCount 或 VehicleCount)

我尝试将 MvxListView 中的绑定更改为

local:MvxBind="ItemsSource AvailableGroups" />

并将与 MvxItemTemplate 的绑定更改为

 local:MvxBind="Text SubGroupCount; ItemClick GroupSelectedCommand " />

 local:MvxBind="Text VehicleCount; ItemClick ItemSelectedCommand " />

并且我为命令 ItemSelectedCommand 创建了必要的处理。

不幸的是它没有触发任何命令。

是否可以从一个模板触发单独的命令,如果可以,我如何将它们绑定到 MvxItemTemplate 中的不同控件?

要完成此操作,您需要有两个单独的命令绑定到行内的视图。

将此添加到您希望单独点击的两个相关布局中:

local:MvxBind="Click OpenFirstCommand"

现在您需要访问列表绑定到的视图模型,而不是行本身的视图模型。您可以采用多种方法来解决这个问题。

  1. 将 RowView 模型包装到包装项中。有关详细信息,请参阅:Binding button click in ListView template MvvMCross

  2. 使用值转换器将 Row 包装到包装项中。关于那个的更多信息:How to binding list item to whether it is contained in another collection

我个人会选择转换器,因为它可以让您的代码更干净。转换器可能如下所示:

 public class ListWrapperValueConverter : MvxValueConverter
        {
            public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                IEnumerable items = value as IEnumerable;

                IList<CellWrapperViewModel<Item>> cellWrapperItems = items.OfType<Item>().Select(x => new CellWrapperViewModel<Item>(x, (BaseViewModel)parameter)).ToList();

                ObservableCollection<CellWrapperViewModel<Item>> itemsList = new ObservableCollection<CellWrapperViewModel<Item>> (cellWrapperItems);

                // If the old collection was observable, forward the triggers, happening on the old one to the new collection.
                if (value as ObservableCollection<Item> != null) {
                    ObservableCollection<Item> documents = value as ObservableCollection<Item>;

                    documents.CollectionChanged += (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) => {
                        switch (e.Action) {
                        default:
                            itemsList.SwitchTo (documents.Select (x => new CellWrapperViewModel<Item> (x, (BaseViewModel)parameter)).ToList ());
                            break;
                        }
                    };
                }

                return itemsList;
            }
        }

包装器将是:

public class CellWrapperViewModel<T>
{
    public T Item { get; set; }

    public BaseViewModel ViewModel { get; set; }

    public CellWrapperViewModel(T item, BaseViewModel viewModel)
    {
        Item = item;
        ViewModel = viewModel;
    }
}

您的 MvxListView 绑定将是:

local:MvxBind="ItemsSource ListWrapper(Items, .)"

行内命令的转换器:

public class OpenFirstCommandValueConverter : MvxValueConverter<CellWrapperViewModel<Item>, MvxCommand>
    {
        protected override MvxCommand Convert(CellWrapperViewModel<Item> value, Type targetType, object parameter, CultureInfo culture)
        {
            BaseViewModel viewModel = value.ViewModel;
            Item item = value.Item;

            return new MvxCommand(() => { viewModel.OptionCommand.Execute((Item)item); });
        }
    }

如果您这样做了,布局的绑定将更改为如下所示:

local:MvxBind="Click OpenFirstCommand(.)"
local:MvxBind="Click OpenSecondCommand(.)"

有关此问题的更多信息也在 mvvmcross GitHub 上:https://github.com/MvvmCross/MvvmCross/issues/35