Xamarin.Forms
Xamarin.Forms copied to clipboard
[Bug] RadioButton does not pass its BindingContext to its content
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
- Create a blank project
- Create a view model for the main page with a property
- Add a RadioButton with a ControlTemplate that includes a ContentPresenter
- 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.
I have the same issue
~~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.
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.
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.
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.
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.