0
votes

I have a Page with a StackLayout using BindableLayout.ItemsSource, inside each item I have a ListView, for each item in this nested ListView I need to do a Binding to a property on the Page's ViewModel. I'm trying to use the Source+Path approach but the app crashes as soon as I open the page that contains this structure.

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>

The exception shows that there is a problem finding the reference to the x:Name I used: Can not find the object referenced by listView

enter image description here

This only happens when I have a nested structure as I mentioned (StackLayout with BindableLayout > ListView). I'm not sure if this is not a supported scenario or if it is a bug.

I tried using different Paths for the binding, but since this is a problem parsing the XAML not finding the x:Name referenced, I don't think it even starts evaluating my Path.

Am I doing something wrong or is this a bug in Xamarin.Forms?

Xamarin.Forms version used: 3.6.0.293080
Repro sample: https://github.com/akamud/BindableLayoutReferenceBug

2
If you need this nested structure, can you define a bindable property ButtonCommand on MessageListViewTemplate, and in MainPage.xaml set up that binding? In MessageListViewTemplate, OnPropertyChanged for ButtonCommand, set the button's Command to new command? - Max Hampton
I understand there are some workarounds available that may work in some scenarios, but the main reason to opening this question is understanding if that scenario is supported and if there's a bug in XF itself. - Mahmoud Ali

2 Answers

1
votes

Maybe, x:Name wasn't recognized at runtime even though you have set it to your content view in XAML. You could raise an issue on GitHub. Here I tried this binding using code behind and it works fine. You could use it as an alternative:

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>

Here, I defined the parent content view as ContentView and named ListView listView.

Please notice that the list view's data template should be a view cell. So I used a view cell to wrap the content here.

1
votes

It was a bug after all, it is now fixed and the above should work: https://github.com/xamarin/Xamarin.Forms/issues/6192