如何在 Xamarin Forms 的可重用 ViewCell 中绑定命令?
Posted
技术标签:
【中文标题】如何在 Xamarin Forms 的可重用 ViewCell 中绑定命令?【英文标题】:How to binding command in reusable ViewCell in Xamarin Forms? 【发布时间】:2019-04-20 15:54:18 【问题描述】:在我的项目中,我有两个 ListView
在不同的 ViewModels
中具有相同的 ViewCell
内容。我将这个ViewCell
提取到其他XAML
文件中以在ListView
中重复使用,如下所示:
<views:MvxContentPage.Content>
<ScrollView x:Name="scrollList">
<StackLayout x:Name="Root">
<!-- ... -->
<repeater:RepeaterView x:Name="MainList" ShowSeparator="False"
SelectedItemCommand="Binding SelectedCommand"
IsVisible="True"
ItemsSource="Binding Items">
<repeater:RepeaterView.ItemTemplate>
<DataTemplate>
<local:ItemList FavoriteCommand="Binding path=FavCommand, Source=x:Reference MainList"
FavoriteCommandParameter="Binding ."/>
</DataTemplate>
</repeater:RepeaterView.ItemTemplate>
</repeater:RepeaterView>
<!-- ... -->
</StackLayout>
</ScrollView>
</views:MvxContentPage.Content>
...
这可以完美地显示数据,但是在标签中绑定命令时,它不起作用。
<views:MvxViewCell
xmlns="http://xamarin.com/schemas/2014/forms"
x:TypeArguments="viewModels:ItemListViewModel"
xmlns:viewModels="clr-namespace:Template.Core.ViewModels;assembly=Template.Core"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Template.Core.Views.ItemList"
xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
xmlns:iconize="clr-namespace:Plugin.Iconize;assembly=Plugin.Iconize"
xmlns:Helpers="clr-namespace:Template.Core.Helpers">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="6*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="ukflag"
Grid.Row="1"
Grid.RowSpan="4"
WidthRequest="50"
HeightRequest="80"
Grid.Column="0" />
<Label Text="Binding Nombre"
Grid.Row="1"
Grid.Column="1"
FontAttributes="Bold"
FontSize="15" />
<Label Text="Binding Direcciones[0].toString"
Grid.Row="2"
Grid.Column="1"
FontSize="11" />
<iconize:IconLabel Text="fas-heart"
BackgroundColor="Transparent"
Grid.Row="1"
Grid.Column="2"
FontSize="35"
Grid.RowSpan="2"
VerticalOptions="Center">
<iconize:IconLabel.GestureRecognizers>
<TapGestureRecognizer Command="Binding FavCommand"
CommandParameter="Binding ." />
</iconize:IconLabel.GestureRecognizers>
</iconize:IconLabel>
<StackLayout Orientation="Horizontal"
Grid.Row="3"
Grid.Column="1">
<iconize:IconLabel Text="fas-map-marker-alt"
TextColor="Black"
FontSize="15" />
<Label Text="Binding Distancia"
FontSize="13" />
</StackLayout>
</Grid>
</views:MvxViewCell>
public partial class ItemList
public ItemList()
InitializeComponent();
在文件中分离 ViewCell 之前,绑定可以正常工作,但现在不能调用 ViewModel 命令。我的想法是从它所在的视图绑定两个命令。如何做呢?非常感谢!!
【问题讨论】:
你能分享整个 ViewCell 的源代码,包括后面的代码(我猜是ItemList
元素)?看起来BindingContext
设置不正确
您好!我刚刚编辑了代码以显示所有内容。非常感谢!
Humn...您正在使用 MvvmCross,我不知道它是如何工作的,或者它是否会干扰行为,但请查看我的答案,看看它是否适合您。跨度>
【参考方案1】:
我不知道您对 Xamarin Forms 的熟练程度如何,但绝对不是初学者的代码。我认为这只是一个误会。正如我所评论的,您所描述的问题看起来像是一个绑定问题。
所以,蛋糕的配方是:
-
在自定义视图单元格中公开您希望能够在外部使用的那些属性;
根据需要将内部视图单元格属性绑定到元素中;
将自定义视图单元与外部绑定一起使用。
一步一步的演练:
1 - 公开启用外部绑定的属性
我相信你只要添加你想绑定到外面的属性,比如可绑定属性,我就会得到预期的结果:
// viewCell's code-behind
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ItemListCell : ContentView
public static BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(ItemListCell));
public string Name
get => (string)GetValue(NameProperty);
set => SetValue(NameProperty, value);
public static BindableProperty FavoriteCommandProperty = BindableProperty.Create(nameof(FavoriteCommand), typeof(ICommand), typeof(ItemListCell));
public ICommand FavoriteCommand
get => (ICommand)GetValue(FavoriteCommandProperty);
set => SetValue(FavoriteCommandProperty, value);
public static BindableProperty FavoriteCommandParameterProperty = BindableProperty.Create(nameof(FavoriteCommandParameter), typeof(object), typeof(ItemListCell));
public object FavoriteCommandParameter
get => GetValue(FavoriteCommandParameterProperty);
set => SetValue(FavoriteCommandParameterProperty, value);
public static BindableProperty DistanceProperty = BindableProperty.Create(nameof(Distance), typeof(string), typeof(ItemListCell));
public string Distance
get => (string)GetValue(DistanceProperty);
set => SetValue(DistanceProperty, value);
public ItemListCell ()
InitializeComponent ();
2 - 在 [view-cell's] 内部绑定上使用属性
在 ViewCell xaml 上,您应该将内部元素属性绑定到已知的绑定上下文(在本例中,我将其命名为 This
)。请参阅Label
和TapGestureRecognizer
上的示例:
// viewCell's XAML
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App2.ItemListCell"
x:Name="This">
<ContentView.Content>
<Grid BindingContext="x:Reference This">
<!-- Keep all the viewcell xaml source code unmodified -->
<Label Text="Binding Name"/>
<!-- ... -->
<iconize:IconLabel.GestureRecognizers>
<TapGestureRecognizer Command="Binding FavoriteCommand"
CommandParameter="Binding FavoriteCommandParameter" />
</iconize:IconLabel.GestureRecognizers>
<!-- ... -->
<!-- Keep all the viewcell xaml source code unmodified -->
</Grid>
</ContentView.Content>
</ContentView>
注意 Grid 的 BindingContext
集和视图单元格与暴露给外部绑定的内部属性的绑定
3 - 使用自定义视图单元格
在这里,您将使用自定义视图单元格并与项目列表对象绑定。然后它应该可以正常工作。应该是这样的:
...
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<local:ItemListCell Name="Binding Nombre"
FavoriteCommand="Binding FavCommand"
FavoriteCommandParameter="Binding ."/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
更新:如果您在页面的视图模型上使用 FavCommand 的单个实现:
<ContentPage ...
x:Name="PageInstance">
...
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<local:ItemListCell Name="Binding Nombre"
FavoriteCommand="Binding BindingContext.FavCommand, Source=x:Reference PageInstance"
FavoriteCommandParameter="Binding ."
.../>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
</ContentPage>
希望对你有帮助。
【讨论】:
您好,我的 Listview 有问题。我已经为 RepaterView 更改了它。我无法绑定我的 FavCommand。我已经调试过,从不调用 set 方法,只调用 get。我已按照您的代码说明进行操作,包括我使用 Listview 进行了测试,但它仍然无法正常工作。会发生什么?谢谢 对不起,我不知道RepeaterView。您正在绑定的FavCommand
是在ItemViewModel
或PageViewModel
上实现的命令?我猜这是第二个。在这种情况下,您必须对客户端上的命令绑定进行交叉绑定。查看我的更新。
@pablogupi ListView
有什么问题?以上是关于如何在 Xamarin Forms 的可重用 ViewCell 中绑定命令?的主要内容,如果未能解决你的问题,请参考以下文章