I read on internet that to make a custom style of radio button you need to create a toggle button style.
So here my style :
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Background" Value="{StaticResource MainOrangeBrush}" />
<Setter Property="Foreground" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Margin" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="Background" Value="{StaticResource MainWhiteBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainOrangeBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{StaticResource MainOrangeBrush}" />
<Setter Property="Background" Value="{StaticResource MainWhiteBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainDarkerGrayBrush}" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="{StaticResource MainOrangeBrush}" />
<Setter Property="Background" Value="{StaticResource MainWhiteBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainOrangeBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="Background" Value="{StaticResource DisableGrayBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainWhiteBrush}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ToggleButton Content="{Binding Path=(Content), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RadioButton}}}" IsChecked="{Binding Path=(IsChecked), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RadioButton}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I still don't fully understand ContentTemplate
and ContentPresenter
. I understand that the content presenter is for everything inside the UI element.
So my problem is that I want to set the fill the same color as the foreground inside the toggle button:
<RadioButton
x:Name="Btn"
Width="40"
Height="40"
HorizontalAlignment="Right"
IsChecked="{Binding IsChecked}"
ToolTip="Btn">
<Path
Width="30"
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="F1 M 19.135,13.006 L 12.740,13.006 L 17.243,0.000 L 0.000,17.142 L 6.397,17.142 L 1.480,30.148 L 19.135,13.006 Z"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}}"
Stretch="Uniform" />
</RadioButton>
This line does not work :
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}}"
Can you help?
I read on internet that to make a custom style of radio button you need to create a toggle button style.
No. You have to create a style for the type RadioButton
. The RelativeSource
binding does not work, because it does not search for ancestors within the control template and will therefore not find the ToggleButton
.
In order to solve your issue, you should create an appropriate style for RadioButton
. It is not necessary to use a toggle button in it, but even if you would, the triggers would be defined in the control template, too. Moreover, the style for the ToggleButton
as you have defined it is implicit (without an x:Key
), which causes it to be applied to every toggle button in scope, not just the RadioButton
and that is not what you want.
I have created a sample style that might look similar to what your are trying to do.
<Style x:Key="FocusVisual1">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" StrokeDashArray="1 2" SnapsToDevicePixels="true" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="OptionMarkFocusVisual1">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="14,0,0,0" StrokeDashArray="1 2" SnapsToDevicePixels="true" StrokeThickness="1" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual1}"/>
<Setter Property="Background" Value="{StaticResource MainOrangeBrush}" />
<Setter Property="Foreground" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource MainDarkerGrayBrush}" />
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Focusable" Value="False" />
<Setter Property="Margin" Value="0" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="radioButtonBorder" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1,1,2,1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid x:Name="markGrid" Margin="2">
<Path x:Name="optionMark"
MinHeight="6"
MinWidth="6"
Margin="2"
Opacity="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="F1 M 19.135,13.006 L 12.740,13.006 L 17.243,0.000 L 0.000,17.142 L 6.397,17.142 L 1.480,30.148 L 19.135,13.006 Z"
Fill="{TemplateBinding Foreground}"
Stretch="Uniform" />
</Grid>
</Border>
<ContentPresenter x:Name="contentPresenter" Grid.Column="1" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource OptionMarkFocusVisual1}"/>
<Setter Property="Padding" Value="4,-1,0,0"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" TargetName="radioButtonBorder" Value="{StaticResource MainWhiteBrush}"/>
<Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="{StaticResource MainOrangeBrush}"/>
<Setter Property="Fill" TargetName="optionMark" Value="{StaticResource MainDarkerGrayBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="radioButtonBorder" Value="{StaticResource DisableGrayBrush}"/>
<Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="{StaticResource MainWhiteBrush}"/>
<Setter Property="Fill" TargetName="optionMark" Value="{StaticResource MainDarkerGrayBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="radioButtonBorder" Value="{StaticResource MainWhiteBrush}"/>
<Setter Property="BorderBrush" TargetName="radioButtonBorder" Value="{StaticResource MainDarkerGrayBrush}"/>
<Setter Property="Fill" TargetName="optionMark" Value="{StaticResource MainOrangeBrush}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Opacity" TargetName="optionMark" Value="1"/>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Opacity" TargetName="optionMark" Value="0.56"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The result looks like below. It is still a radio button, but with your custom Path
as option mark and your custom colors applied to the respective states.
In this example, the Path
is embedded in the control template and the Content
, here the text Test is still applied. You can of course further customize the template so that it fits your requirements.
If you want the Content
and the option mark to be customizable without creating a different style, you will have to create a custom radio button control derived from RadioButton
and expose a dependency property to specify the option mark content. Then you can bind it in the control template, but that is another question.