MvxItemTemplate ItemClick绑定

时间:2015-01-07 11:50:55

标签: xamarin.android mvvmcross

我在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中的不同控件?

1 个答案:

答案 0 :(得分:1)

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

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

local:MvxBind="Click OpenFirstCommand"

现在您需要访问列表绑定的viewmodel而不是行本身的Viewmodel。您可以采取多种方法来解决这个问题。

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

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

  3. 我个人会选择转换器,因为它可以使您的代码更加干净。转换器可能看起来像:

     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;
                }
            }
    

    The Wrapper将是:

    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