【问题标题】:How to change radio button's toggle button to an image in wpf (for grouped radio buttons)?如何将单选按钮的切换按钮更改为 wpf 中的图像(用于分组单选按钮)?
【发布时间】:2021-08-07 10:09:15
【问题描述】:

我在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}" />

这是我的按钮的样子:


当我选择一个菜单项时,它将如下所示:

(IsChecked true 和 false 的图像对于我所有的菜单项(即RadioButtons)都是相同的)

问题是,我是否必须为每个按钮创建一个ResourceDictionary,以便在我选择它们时它们的图像会发生变化(当然,更改它们的默认图像)?


这是我想要实现的:

【问题讨论】:

  • 我有一组单选按钮。我已经在我的 app.xaml 中注册了资源字典。让我更新问题以更清楚。
  • 如果下面的答案没有回答问题,我会更新。
  • 图像相同的原因是您为两者提供了相同的图像路径。会不会是因为这个?当我这样做并给出不同的图片时,RadioButton 绘画作品。
  • 是的,它只是用于测试目的。但是,如果我更改每个项目的默认和“选定”图像,是否需要为每个按钮创建另一个资源字典?

标签: wpf xaml radio-button


【解决方案1】:

有多种方法可以实现这一点,但我认为最直接的方法是定义一个自定义 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]"/>

【讨论】:

  • @Hacki,我认为这似乎是理想的解决方案。当您想向 RadioButton 添加新功能时,您可以在单个结构中进行必要的安排。
  • 我们的 xaml 中真的需要这些吗?
  • 我试过这个,但是,我的正常/默认图像没有显示。但是,当我选择一个图像时,它现在会根据我选择的菜单项更改其图像。
  • 我似乎无法显示正常/默认图像,因此我将您的答案与@saklanmaz 的答案混合在一起,现在它可以工作了! (对我的预期行为)这个答案:当我选择它时更改了 RadioButton 的图像
  • 如果您选择在每个 SampleRadioButtons 中设置特定图像,则无需设置默认图像。 URI 字符串到图像的正确格式取决于您如何在应用程序中包含这些图像。这只是我认为直截了当的方法的一个示例。
【解决方案2】:

在这种情况下,我认为在IsChecked的情况下无需更改图像。我把上面的图片链接到 RadioButton Tag 上(我做的很快,你可以把它链接到更方便的地方。)

您现在可以在自己的 xaml 代码中使用标记作为图像地址路径。

<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>

【讨论】:

  • 我已经这样做了。请参阅我更新的帖子:D
  • 我无法根据 xaml 端的 IsChecked true 和 false 更改背景图像。花一点时间就可以解决。这就是我所能做的:)
  • 好吧,这解决了“默认”图像显示(未单击按钮时)。我仍然需要弄清楚如何根据按钮状态更改图像。
  • 你可以通过给 RadioButton 一个名字来改变它,在后台代码中使用RadioBt.Tag = "/Images/image.png";。
  • 如何在后面的代码中做到这一点?这是我第一次在 wpf 中创建 ui。
猜你喜欢
  • 2011-01-22
  • 2021-02-23
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多