Reputation: 973
I change my radio button's image (when clicked or not) in a ResourceDictionary
like this:
<Style TargetType="{x:Type RadioButton}"
x:Key="MenuButtonTheme">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Image x:Name="SidebarRadioButtonMenuIcon"
Source="/UiDesign/Images/SidebarIcons/logout.png"
Width="18.57"
Height="18.57"
Grid.Column="0" />
<TextBlock x:Name="SidebarRadioButtonMenuText"
Text="{TemplateBinding Property=Content}"
VerticalAlignment="Center"
Foreground="#7D8083"
FontSize="14.59"
FontWeight="Bold"
FontFamily="/UiDesign/Fonts/#Nunito"
Margin="12,0,0,0"
Grid.Column="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter TargetName="SidebarRadioButtonMenuText"
Property="Foreground"
Value="#F54342" />
<Setter TargetName="SidebarRadioButtonMenuIcon"
Property="Source"
Value="/UiDesign/Images/SidebarIcons/Selected/logout.png" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background"
Value="Transparent" />
</Style.Setters>
</Style>
The code above is working just fine. But my menu consists of more than 1 radio buttons.
This is how I apply my style:
<RadioButton Content="Dashboard"
Grid.Column="1"
Grid.Row="0"
Style="{StaticResource MenuButtonTheme}" />
This is how my buttons look like:
When I select a menu item, it will look like this:
(the images for IsChecked
true and false are all the same for all my menu items (which are RadioButton
s))
The question is, do I have to create a ResourceDictionary
for each button so that their image will change when I select on them (and of course, change their default image)?
This is want I want to achieve:
Upvotes: 0
Views: 479
Reputation: 3556
There are a variety of ways to accomplish this but I think the straightforward way is to define a custom RadioButton which has dependency properties for URI strings to images for different states and bind them from XAML.
Let's say, we create SampleRadioButton which has NormalImageUriString
and CheckedImageUriString
dependency properties and a converter for converting URI string to BitmapImage.
public class SampleRadioButton : RadioButton
{
public string NormalImageUriString
{
get { return (string)GetValue(NormalImageUriStringProperty); }
set { SetValue(NormalImageUriStringProperty, value); }
}
public static readonly DependencyProperty NormalImageUriStringProperty =
DependencyProperty.Register("NormalImageUriString", typeof(string), typeof(SampleRadioButton), new PropertyMetadata(null));
public string CheckedImageUriString
{
get { return (string)GetValue(CheckedImageUriStringProperty); }
set { SetValue(CheckedImageUriStringProperty, value); }
}
public static readonly DependencyProperty CheckedImageUriStringProperty =
DependencyProperty.Register("CheckedImageUriString", typeof(string), typeof(SampleRadioButton), new PropertyMetadata(null));
}
public class ImageUriStringConverver : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not string source)
return DependencyProperty.UnsetValue;
return new BitmapImage(new Uri(source, UriKind.Relative));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And edit XAML to bind these dependency properties using the converter.
<local:ImageUriStringConverver x:Key="ImageUriStringConverterKey"/>
<Style TargetType="{x:Type local:SampleRadioButton}">
<Setter Property="NormalImageUriString" Value="[URI string to default image for normal state]"/>
<Setter Property="CheckedImageUriString" Value="[URI string to default image for checked state]"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SampleRadioButton}">
<Grid Background="{TemplateBinding Background}">
...
<Image x:Name="SidebarRadioButtonMenuIcon"
Source="{TemplateBinding NormalImageUriString, Converter={StaticResource ImageUriStringConverterKey}}"
...
/>
<TextBlock x:Name="SidebarRadioButtonMenuText"
...
/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="SidebarRadioButtonMenuText" Property="Foreground" Value="#F54342" />
<Setter TargetName="SidebarRadioButtonMenuIcon" Property="Source" Value="{Binding CheckedImageUriString, RelativeSource={RelativeSource AncestorType={x:Type local:SampleRadioButton}}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then we can set specific images by setting these dependency properties in each SampleRadioButton.
<local:SampleRadioButton Content="Sample"
NormalImageUriString="[URI string to specific image for normal state]"
CheckedImageUriString="[URI string to specific image for checked state]"/>
Upvotes: 2
Reputation: 564
In this case, I think there is no need to change the image in the case of IsChecked. I linked the picture above to the RadioButton Tag (I did it quickly, you can link it to something more convenient.)
You can now use Tag as image address path in your own xaml code.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type RadioButton}"
x:Key="MenuButtonTheme">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Image x:Name="SidebarRadioButtonMenuIcon"
Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"
Width="18.57"
Height="18.57"
Grid.Column="0" />
<TextBlock x:Name="SidebarRadioButtonMenuText"
Text="{TemplateBinding Property=Content}"
VerticalAlignment="Center"
Foreground="#7D8083"
FontSize="14.59"
FontWeight="Bold"
FontFamily="/UiDesign/Fonts/#Nunito"
Margin="12,0,0,0"
Grid.Column="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter TargetName="SidebarRadioButtonMenuText"
Property="Foreground"
Value="#F54342" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background"
Value="Transparent" />
</Style.Setters>
</Style>
MainWindow.xaml
<RadioButton Content="Dashboard"
Grid.Column="1"
Grid.Row="0"
Style="{StaticResource MenuButtonTheme}"
Tag="/Images/image2.png">
</RadioButton>
Upvotes: 0