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"
现在您需要访问列表绑定到的视图模型,而不是行本身的视图模型。您可以采用多种方法来解决这个问题。
将 RowView 模型包装到包装项中。有关详细信息,请参阅:Binding button click in ListView template MvvMCross
使用值转换器将 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
我在 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"
现在您需要访问列表绑定到的视图模型,而不是行本身的视图模型。您可以采用多种方法来解决这个问题。
将 RowView 模型包装到包装项中。有关详细信息,请参阅:Binding button click in ListView template MvvMCross
使用值转换器将 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