xamlradio-buttonmauicontroltemplatevisualstatemanager

How to change the Text color of ContentPresenter based on the control state in .Net MAUI


My question is an extension to this question where I want to change the text color based on the state of the radio button. I want it white if checked and black if unchecked.

Details: I am using a custom styled Radio Button in my application following Redefine RadioButton appearance where it creates ControlTemplate to customize the appearance and uses ContentPresenter for displaying text/content.

I modified it to the shape I want, but unable to change the Text color based on the whether the radio button is checked or not.

Below is my code.

<ControlTemplate x:Key="RadioButtonTemplate">
    <Border x:Name="RadioBorder1"
            StrokeShape="RoundRectangle 3"
            BackgroundColor="#F3F2F1"
            HeightRequest="30"
            WidthRequest="120">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroupList>
                <VisualStateGroup x:Name="CheckedStates">
                    <VisualState x:Name="Checked">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="MediumPurple" />
                            <Setter Property="Stroke" Value="MediumPurple" />
                            <Setter TargetName="check" Property="Opacity" Value="1" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="Unchecked">
                        <VisualState.Setters>
                            <Setter Property="BackgroundColor" Value="#F3F2F1" />
                            <Setter Property="Stroke" Value="#F3F2F1" />
                            <Setter TargetName="check" Property="Opacity" Value="0" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateGroupList>
        </VisualStateManager.VisualStateGroups>
        <Grid Margin="4" WidthRequest="120">
            <Grid WidthRequest="120" HeightRequest="30">
                <RoundRectangle />
                <RoundRectangle x:Name="check" />
            </Grid>
            <ContentPresenter HorizontalOptions="StartAndExpand" Padding="5,1,1,1" />
        </Grid>
    </Border>
</ControlTemplate>

<Style TargetType="RadioButton">
            <Setter Property="ControlTemplate"
                    Value="{StaticResource RadioButtonTemplate}" />
</Style>

<!--Radio Buttons--> 
<Label Text="What's your favorite color?" />
<VerticalStackLayout RadioButtonGroup.GroupName="colors">
    <HorizontalStackLayout HorizontalOptions="Start" Margin="3,0,0,0">
        <RadioButton Content="Red" CheckedChanged="RadioButton_CheckedChanged" />
        <RadioButton Content="Green" CheckedChanged="RadioButton_CheckedChanged" />
        <RadioButton Content="Blue" CheckedChanged="RadioButton_CheckedChanged" />
    </HorizontalStackLayout>
    <HorizontalStackLayout HorizontalOptions="StartAndExpand">
        <RadioButton Content="Enable" />
        <RadioButton Content="Disable" />
        <RadioButton Content="Other" />
    </HorizontalStackLayout>
    <HorizontalStackLayout HorizontalOptions="CenterAndExpand">
        <RadioButton Content="Working" />
        <RadioButton Content="Turbo Power" />
    </HorizontalStackLayout>
</VerticalStackLayout>

I tried changing the text color on CheckedChanged event, but that didn't help.

private void RadioButton_CheckedChanged(object sender, CheckedChangedEventArgs e)

{ RadioButton? button = sender as RadioButton;

if ((button?.IsChecked ?? false) == true)
{
    val = button?.Content?.ToString() ?? string.Empty;
    //button.TextColor = Colors.White;
}

}

This is what I have now and I am trying to change the text color to white for the selected item.

Thanks for your help.


Solution

  • You could use Relative Bindings and Binding value converters to solve it.

    What I am going to do is to bind the Label's TextColor property to the RadioButton's IsChecked property,

    <Label Text="Cat"
           TextColor="{Binding IsChecked,Source={RelativeSource AncestorType={x:Type RadioButton}},Converter={StaticResource isCheckedConverter}}"
           HorizontalOptions="Center"
           VerticalOptions="End" />
    

    So, we need a value converter to convert IsChecked property value (True/False) to the Label TextColor value. We create a new Class called IsCheckedConverter.cs,

    public class IsCheckedConverter : IValueConverter
    {
        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
        {
            bool a = (bool)value;
            if (a)
            {
                return Colors.White;
            }
            else {
                return Colors.Black;           
            }         
        }
    
        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    

    Don't forget to put it in the ContentPage.Resources

    <ContentPage.Resources>
        ......
    
        <local:IsCheckedConverter x:Key="isCheckedConverter"/>
    </ContentPage.Resources>