如何将单选按钮的切换按钮更改为 wpf 中的图像(用于分组单选按钮)?
How to change radio button's toggle button to an image in wpf (for grouped radio buttons)?
我在 ResourceDictionary
中更改单选按钮的图像(无论是否单击),如下所示:
<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>
上面的代码工作正常。但是我的菜单包含 1 个以上的单选按钮。
我是这样应用我的风格的:
<RadioButton Content="Dashboard"
Grid.Column="1"
Grid.Row="0"
Style="{StaticResource MenuButtonTheme}" />
这是我的按钮的样子:
当我 select 一个菜单项时,它看起来像这样:
(IsChecked
true 和 false 的图像对于我所有的菜单项(都是 RadioButton
s)都是一样的)
问题是,我是否必须为每个按钮创建一个 ResourceDictionary
,以便当我在它们上面 select 时它们的图像会改变(当然,还要改变它们的默认图像)?
这是我想要实现的:
在这种情况下,我认为在IsChecked的情况下没有必要更改图像。我 link 将上面的图片编辑到 RadioButton 标签(我做的很快,你可以 link 它更方便。)
您现在可以在自己的 xaml 代码中使用 Tag 作为图像地址路径。
<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>
有多种方法可以实现这一点,但我认为最直接的方法是定义一个自定义 RadioButton,它具有 URI 字符串到不同状态图像的依赖属性,并将它们从 XAML.
比方说,我们创建 SampleRadioButton,它具有 NormalImageUriString
和 CheckedImageUriString
依赖属性和一个将 URI 字符串转换为 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();
}
}
并编辑 XAML 以使用转换器绑定这些依赖属性。
<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>
然后我们可以通过在每个 SampleRadioButton.
中设置这些依赖属性来设置特定的图像
<local:SampleRadioButton Content="Sample"
NormalImageUriString="[URI string to specific image for normal state]"
CheckedImageUriString="[URI string to specific image for checked state]"/>
我在 ResourceDictionary
中更改单选按钮的图像(无论是否单击),如下所示:
<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>
上面的代码工作正常。但是我的菜单包含 1 个以上的单选按钮。
我是这样应用我的风格的:
<RadioButton Content="Dashboard"
Grid.Column="1"
Grid.Row="0"
Style="{StaticResource MenuButtonTheme}" />
这是我的按钮的样子:
当我 select 一个菜单项时,它看起来像这样:
(IsChecked
true 和 false 的图像对于我所有的菜单项(都是 RadioButton
s)都是一样的)
问题是,我是否必须为每个按钮创建一个 ResourceDictionary
,以便当我在它们上面 select 时它们的图像会改变(当然,还要改变它们的默认图像)?
这是我想要实现的:
在这种情况下,我认为在IsChecked的情况下没有必要更改图像。我 link 将上面的图片编辑到 RadioButton 标签(我做的很快,你可以 link 它更方便。)
您现在可以在自己的 xaml 代码中使用 Tag 作为图像地址路径。
<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>
有多种方法可以实现这一点,但我认为最直接的方法是定义一个自定义 RadioButton,它具有 URI 字符串到不同状态图像的依赖属性,并将它们从 XAML.
比方说,我们创建 SampleRadioButton,它具有 NormalImageUriString
和 CheckedImageUriString
依赖属性和一个将 URI 字符串转换为 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();
}
}
并编辑 XAML 以使用转换器绑定这些依赖属性。
<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>
然后我们可以通过在每个 SampleRadioButton.
中设置这些依赖属性来设置特定的图像<local:SampleRadioButton Content="Sample"
NormalImageUriString="[URI string to specific image for normal state]"
CheckedImageUriString="[URI string to specific image for checked state]"/>