如何在Xamarin.Forms中将嵌套的Layout与外部ContentView绑定?

时间:2019-05-13 14:30:55

标签: xamarin xamarin.forms

我有一个Page和一个StackLayout,使用BindableLayout.ItemsSource,在每个项目中我都有一个ListView,为此嵌套ListView中的每个项目我都需要对页面的ViewModel上的属性执行Binding。我正在尝试使用Source+Path方法,但是一旦打开包含该结构的页面,应用就会崩溃。

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
  x:Class="BindableLayoutReferenceBug.ListViewPage"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:local="clr-namespace:BindableLayoutReferenceBug">
  <StackLayout BindableLayout.ItemsSource="{Binding Items}">
    <BindableLayout.ItemTemplate>
      <DataTemplate>
        <local:MessageListViewTemplate />
      </DataTemplate>
    </BindableLayout.ItemTemplate>
  </StackLayout>
</ContentPage>

MessageListViewTemplate.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
  x:Class="BindableLayoutReferenceBug.MessageListViewTemplate"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  x:Name="listView">
  <ListView ItemsSource="{Binding Options}">
    <ListView.ItemTemplate>
      <DataTemplate>
        <StackLayout>
          <Label Text="{Binding .}" />
          <Button
            BackgroundColor="Blue"
            Command="{Binding Source={x:Reference Name=listView}, Path=Parent.BindingContext.ShowMessageCommand}"
            CommandParameter="{Binding .}"
            Text="Show Message" />
        </StackLayout>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentView>

该异常表明找到对我使用的x:Name的引用存在问题:找不到listView引用的对象

enter image description here

仅当我有提到的嵌套结构(带有BindableLayout的StackLayout> ListView)时,才会发生这种情况。我不确定这是否不是受支持的方案,或者是否是错误。

我尝试使用不同的路径进行绑定,但是由于这是解析XAML找不到引用的x:Name的问题,所以我认为它甚至没有开始评估我的Path。

我是在做错什么还是Xamarin.Forms中的错误?

使用的Xamarin.Forms版本:3.6.0.293080
复制样本:https://github.com/akamud/BindableLayoutReferenceBug

2 个答案:

答案 0 :(得分:1)

也许,即使您在XAML中将x:Name设置为内容视图,也无法在运行时识别它。您可以在GitHub上提出问题。 在这里,我尝试使用后面的代码进行此绑定,并且工作正常。您可以使用它作为替代:

public MessageListViewTemplate()
{
    InitializeComponent();

    listView.ItemTemplate = new DataTemplate(() =>
    {
        ViewCell viewCell = new ViewCell();
        Label label = new Label();
        label.SetBinding(Label.TextProperty, new Binding("."));

        Button button = new Button() { Text = "Show Message", BackgroundColor = Color.Blue };
        button.SetBinding(Button.CommandProperty, new Binding("Parent.BindingContext.ShowMessageCommand", source: ContentView));
        button.SetBinding(Button.CommandParameterProperty, new Binding("."));


        viewCell.View = new StackLayout
        {
            Children =
            {
                label,
                button
            }
        };

        return viewCell;
    });
}

XAML:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="BindableLayoutReferenceBug.MessageListViewTemplate" 
             x:Name="ContentView">
    <StackLayout>
        <ListView ItemsSource="{Binding Options}" x:Name="listView" HasUnevenRows="True">


        </ListView>

    </StackLayout>

</ContentView>

在这里,我将父内容视图定义为ContentView,并将其命名为ListView listView

请注意,列表视图的数据模板应为视图单元格。因此,我使用视图单元将内容包装在这里。

答案 1 :(得分:1)

毕竟这是一个bug,现在已经修复,上面的命令应该可以工作:https://github.com/xamarin/Xamarin.Forms/issues/6192