maui icon indicating copy to clipboard operation
maui copied to clipboard

Children in CollectionView do not inherit BindingContext

Open pekspro opened this issue 3 years ago • 2 comments
trafficstars

Description

I have two issues with BindingContext. First issue is that will not set the correct BindingContext on a ContentView:

<CollectionView.ItemTemplate>
    <DataTemplate>
        <vm:PersonView BindingContext="{Binding Leader}"/>
    </DataTemplate>
</CollectionView.ItemTemplate>

But this will;

<CollectionView.ItemTemplate>
    <DataTemplate>
        <Grid>
           <vm:PersonView BindingContext="{Binding Leader}"/>
        </Grid>
    </DataTemplate>
</CollectionView.ItemTemplate>

Second issue is that setting a BindingContext from a list is OK. Sample:

<VerticalStackLayout BindingContext="{Binding TheTeams[0]}">

This works fine when running an application. But if compiled binding are used, this will not compile.

Steps to Reproduce

  1. Create a new MAUI application.
  2. Add a ContentView named PersonView with this XAML content:
<VerticalStackLayout>
    <Label Text="{Binding PersonName}" />
</VerticalStackLayout>
  1. Replace the code in MainPage.xaml.cs:
public record Person (string PersonName);

public record Team (string TeamName, Person Leader);

public record Teams (List<Team> TheTeams);

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();

		Person alice = new Person("Alice");
		Team coders = new Team("Coders", alice);
		Teams teams = new Teams(new List<Team> { coders });

		BindingContext = teams;
	}
}
  1. Replace MainPage.xaml with this:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MauiIssues"
             x:Class="MauiIssues.MainPage"
             >
    <!--Add this to ContentPage to see Issue 2. x:DataType="vm:Teams"-->

    <VerticalStackLayout>
        <Label Text="Issue 1: " />
        <CollectionView ItemsSource="{Binding TheTeams}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <!--
                        Issue 1. This will show nothing. A workaround is to wrap everything in a Grid:
                    
                        <Grid> <vm:PersonView BindingContext="{Binding Leader}"/> </Grid>
                    -->
                    <vm:PersonView BindingContext="{Binding Leader}"/>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>


        <!-- 
            Issue 2. These will not compile when x:DataType="vm:Teams" is added to ContentPage.
        -->
        <Label Text="Issue 2A:" />
        <VerticalStackLayout BindingContext="{Binding TheTeams[0]}">
            <HorizontalStackLayout BindingContext="{Binding Leader}">
                <Label Text="{Binding PersonName}" />
            </HorizontalStackLayout>
        </VerticalStackLayout>

        <Label Text="Issue 2B:" />
        <CollectionView ItemsSource="{Binding TheTeams}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <VerticalStackLayout>
                        <HorizontalStackLayout BindingContext="{Binding Leader}">
                            <Label Text="{Binding PersonName}" />
                        </HorizontalStackLayout>
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>
  1. Run the application. You will see nothing on issue 1. Wrap the view in Grid and it will work.
  2. Add x:DataType="vm:Teams" in the ContentPage tag.
  3. The project will no longer compile.

Full sample: https://github.com/pekspro/MauiIssues/tree/9131_BindingContext_cannot_be_changed

Version with bug

6.0.408 (current)

Last version that worked well

Unknown/Other

Affected platforms

Windows, I was not able test on other platforms

Affected platform versions

Windows 10.0.17763.0

Did you find any workaround?

Yes, described in the code.

Relevant log output

No response

pekspro avatar Aug 02 '22 08:08 pekspro

Ideally we could just change this line

https://github.com/dotnet/maui/blob/733ba2f93b73e1acacc23d593c5380f188c6b1c9/src/Compatibility/Core/src/Android/CollectionView/TemplatedItemViewHolder.cs#L67

to use

VisualElement.SetInheritedBindingContext(View, itemBindingContext);

But then that causes the BC to flow from the parent which we don't want.

There's a similar case with this if you look at ContentPresenter where it overrides this

		internal override void SetChildInheritedBindingContext(Element child, object context)
		{
			// We never want to use the standard inheritance mechanism, we will get this set by our parent
		}

so that the BC doesn't flow from the parent. We don't really have a place to do this with CV but maybe this can be reworked so the BindableObject can get flagged to ignore the parent BC.

PureWeen avatar Aug 02 '22 19:08 PureWeen

I've updated sample application to .NET 7. The same issue remains, and it also an issue on Android.

pekspro avatar Nov 11 '22 17:11 pekspro

Verified this on Visual Studio Enterprise 17.7.0 Preview 1.0. Repro on Windows 11 with below Project: 9131.zip

Issue1: Show nothing for Issue1 in application. image

Issue2: Run failed with Error XFC0045 "Binding: Property "Leader" not found on "MauiApp11.Teams"." after adding x:DataType="vm:Teams" to ContentPage. image

XamlTest avatar May 25 '23 06:05 XamlTest