如何将单选按钮的切换按钮更改为 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 的图像对于我所有的菜单项(都是 RadioButtons)都是一样的)

问题是,我是否必须为每个按钮创建一个 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,它具有 NormalImageUriStringCheckedImageUriString 依赖属性和一个将 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]"/>