Xamarin.Forms icon indicating copy to clipboard operation
Xamarin.Forms copied to clipboard

[Bug] RadioButton does not pass its BindingContext to its content

Open sjordanGSS opened this issue 3 years ago • 6 comments

Description

If a RadioButton is created with a ControlTemplate to allow it to display its .Content as a view, the BindingContext of the RadioButton doesn't get passed to .Content

Steps to Reproduce

  1. Create a blank project
  2. Create a view model for the main page with a property
  3. Add a RadioButton with a ControlTemplate that includes a ContentPresenter
  4. Set .Content on the RadioButton to a view e.g. a Label and create a binding to the viewmodel property

a Repro is available here: https://github.com/sjordanGSS/radio-button-content-binding-context-repro

Expected Behavior

The Label should display the value of the bound property

Actual Behavior

The Label does not display the value of the bound property

Basic Information

  • Version with issue: Xamarin.Forms 5.0.0sr9
  • Last known good version: Not Tested
  • Platform Target Frameworks:
    • iOS: Not Tested
    • Android: 12.2
    • UWP: Not Tesed
  • Android Support Library / AndroidX Version:
  • NuGet Packages:
  • Affected Devices: As implied above, I have only observed this on Android devices, I have tested on Android 7.1 and 11.

Environment

Show/Hide Visual Studio info

Build Logs

Screenshots

Reproduction Link

Workaround

As demonstrated in the repro project, a RelativeSource binding can be used to traverse the view hierarchy until the desired viewmodel is found and then bound to.

sjordanGSS avatar Feb 22 '22 09:02 sjordanGSS

I have the same issue

Ruvi1996 avatar Feb 28 '22 12:02 Ruvi1996

~~Beginning to wonder whether or not this is actually a RadioButton bug, at first I thought I'd found a divergence in behaviour between the way that RadioButton and e.g. ContentPage handle ControlTemplates, but I've just reviewed a ControlTemplate that I wrote for ContentPage and noticed that it uses~~

BindingContext="{Binding Source={RelativeSource TemplatedParent}, Path=BindingContext}"

~~on the top level control within the template, which will obviously set the BindingContext of all controls within the template to the BindingContext of whatever they're templated onto. I've yet to test this on a RadioButton but I have a sinking feeling that it'll produce the expected behaviour~~

Sorry I'm getting myself in a right muddle: the ControlTemplate for the ContentPage sets its BindingContext to TemplatedParent.BindingContext so it can bind to properties from the viewmodel, the Content of the ContentPage doesn't have to do this. This does deviate from how things work with RadioButton where the Content's BindingContext doesn't get set, as is described by the OP.

sjordanGSS avatar Mar 15 '22 14:03 sjordanGSS

Do you still have a repro/workaround for this? The repro link is dead. As you describe I also can't bind the content of RadioButtons inside a BindableLayout.

RhomGit avatar Aug 16 '22 03:08 RhomGit

Do you still have a repro/workaround for this? The repro link is dead. As you describe I also can't bind the content of RadioButtons inside a BindableLayout.

Repro link seems to be working fine for me, the repo is still up and should be publicly available. What error do you get when clicking it?

As noted in the OP, you can use a RelativeSource binding in your .Content with Mode set to FindAncestorBindingContext to traverse the view hierarchy and find the proper binding target. So if you're binding to a viewmodel called RadioButtonViewModel with a property RadioButtonText, you should be able to use

<Label Text={Binding Source={RelativeBinding Mode=AncestorBindingContext, AncestorType={x:type viewmodels:RadioButtonViewModel}}, Path=RadioButtonText}" />

in your .Content.

sjordanGSS avatar Aug 16 '22 08:08 sjordanGSS

I think your repro is set to private.

I had to change your above syntax according to: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings#bind-to-an-ancestor however your workaround worked and I am now able to move forward. Thanks very much, this should be in the official XF documentation for radio buttons as I think its critical to anyone trying to use it like this. All the static samples for RadioButtons are pretty elementary and almost worthless without data binding.

RhomGit avatar Aug 16 '22 10:08 RhomGit

I think your repro is set to private.

I had to change your above syntax according to: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings#bind-to-an-ancestor however your workaround worked and I am now able to move forward. Thanks very much, this should be in the official XF documentation for radio buttons as I think its critical to anyone trying to use it like this. All the static samples for RadioButtons are pretty elementary and almost worthless without data binding.

It was set to private. I don't even know how I did that. It should be set to public now. Thanks!

Great to hear you've been able to solve your problem. I think this is a bug rather than an intended feature since, as I've noted, it is inconsistent with the way that other controls handle templates: ContentPage will pass the BindingContext to its .Content correctly when using a ControlTemplate.

sjordanGSS avatar Aug 16 '22 10:08 sjordanGSS