【问题标题】:How to binding command in reusable ViewCell in Xamarin Forms?如何在 Xamarin Forms 的可重用 ViewCell 中绑定命令?
【发布时间】: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,我不知道它是如何工作的,或者它是否会干扰行为,但请查看我的答案,看看它是否适合您。跨度>

标签: listview xamarin xamarin.forms binding


【解决方案1】:

我不知道您对 Xamarin Forms 的熟练程度如何,但绝对不是初学者的代码。我认为这只是一个误会。正如我所评论的,您所描述的问题看起来像是一个绑定问题。

所以,蛋糕的配方是:

  1. 在自定义视图单元格中公开您希望能够在外部使用的那些属性;
  2. 根据需要将内部视图单元格属性绑定到元素中;
  3. 将自定义视图单元与外部绑定一起使用。

一步一步的演练:

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)。请参阅LabelTapGestureRecognizer 上的示例:

// 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 是在ItemViewModelPageViewModel 上实现的命令?我猜这是第二个。在这种情况下,您必须对客户端上的命令绑定进行交叉绑定。查看我的更新。
  • @pablogupi ListView 有什么问题?
猜你喜欢
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 2018-08-04
  • 2021-04-05
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 2021-11-26
相关资源
最近更新 更多