dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.21k stars 1.74k forks source link

ControlTemplate not propagating the BindingContext correctly if set through Binding #22607

Open strajk- opened 5 months ago

strajk- commented 5 months ago

Description

It's a repeat of the Issue #12470 that was supposedly fixed with the Pull #12536 except in my case the propagation doesn't seem to work correctly if the ControlTemplate is set through Binding.

Steps to Reproduce

  1. Create a Template without a BindingContext, add it as a Resource in your ContentPage
    <ContentPage.Resources>
    <ResourceDictionary>
         <ControlTemplate  x:Key="String_Template" >
             <Entry Text="{Binding Value, Mode=TwoWay}"/>
         </ControlTemplate>
    </ResourceDictionary>
    </ContentPage.Resources>
  2. A Property to Bind to that handles the ControlTemplate swapping
    
    public static readonly BindableProperty TypeTemplateProperty = BindableProperty.Create(
    nameof(TypeTemplate),
    typeof(ControlTemplate),
    typeof(ContentPage),
    defaultValue: null,
    defaultBindingMode: BindingMode.OneWay);

public ControlTemplate TypeTemplate { get => (ControlTemplate)GetValue(TypeTemplateProperty); set => SetValue(TypeTemplateProperty, value); }

3. Add a ContentView that will show the Template set in TypeTemplate
```xaml
<Grid BindingContext="{Binding Source={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContentPage}}}">
    <ContentView ControlTemplate="{Binding TypeTemplate}"/>
</Grid>
  1. Some logic to set our TypeTemplate
    Resources.TryGetValue("String_Template", out object template);
    if (template != null && template is ControlTemplate cTemplate) {
    TypeTemplate = cTemplate;
    }
  2. Value Property that we want to show in our ControlTemplate
    public object Value { get; set; } = "Test";

Link to public reproduction project repository

No response

Version with bug

8.0.10 SR3

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

API 34 (Android 14.0) - Didn't test others

Did you find any workaround?

Adding the BindingContext on the Control that's defined inside the ControlTemplate to "renew" the BindingContext fixes it.

<ControlTemplate  x:Key="String_Template" >
    <Entry Text="{Binding Value, Mode=TwoWay}" BindingContext="{Binding BindingContext, Source={RelativeSource Mode=TemplatedParent}}"/>
</ControlTemplate>

It also works if I were to set the ControlTemplate as a StaticResource like this:

<Grid BindingContext="{Binding Source={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContentView}}}">
    <ContentView ControlTemplate="{StaticResource String_Template}"/>
</Grid>

But that defeats the purpose of being able to dynamically switch between ControlTemplates without extra C# code.

Relevant log output

No response

github-actions[bot] commented 5 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

AceCoderLaura commented 3 months ago

I've created a repro project for this issue here: https://github.com/AceCoderLaura/MauiBugs/tree/master/ContentViewBug

I might create a repro for the binding scenario too if I get some time, but it's ultimately the same bug.