在运行时具有自定义图像和文本更改的 RadioButton

RadioButton with custom image and text change at runtime

我有一个自定义 RadioButton 样式,其中有一个 Image 和 2 个 TextBlock

<Style x:Key="ToggleButton_Chose" TargetType="{x:Type ToggleButton}" >
    
    <Setter Property="Background" Value="#32353B" />
    <Setter Property="Margin" Value="10,5"/>
    <Setter Property="Height" Value="45" />
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="Padding" Value="1" />
    <Setter Property="HorizontalAlignment" Value="Stretch"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <StackPanel>
                    <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            Background="{TemplateBinding Background}">
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0">
                            <ContentPresenter HorizontalAlignment="Left"                  
                                          VerticalAlignment="Center"/>

                            <Image Source="{TemplateBinding Button.Tag}"  HorizontalAlignment="Left" Stretch="Uniform" Width="45" IsEnabled="True" />

                            <StackPanel Margin="2">
                                <TextBlock Foreground="#DCDDDE"  FontSize="18" FontFamily="Arial">Strona</TextBlock>
                                <TextBlock Foreground="#52555C"  FontSize="12" FontFamily="Arial"> Login</TextBlock>
                            </StackPanel>
                        </StackPanel>
                    </Border>
                </StackPanel>

            </ControlTemplate>

        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsChecked" Value="True">
            <Setter Property="Background" Value="#282B2E"/>
        </Trigger>
  
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background">
                <Setter.Value>
                    <SolidColorBrush Color="#FF282B2E" Opacity="0.5"/>
                </Setter.Value>
            </Setter>
        </Trigger>
      
    </Style.Triggers>
</Style>

当我在运行时创建一个新按钮时,设置 Style 并且我想更改 Image 和每个 RadioButton 的文本。现在我正在考虑为此使用 Tag

RadioButton radioButton = new RadioButton();

 radioButton.GroupName = "Side";

 radioButton.Style = (Style)Resources["ToggleButton_Chose"];

 radioButton.Tag = new BitmapImage(new Uri("https://www.google.com/favicon.ico"));

还有其他方法可以设置吗? 我将有大约 100 个 RadioButton,其中任何一个都应该有不同的图像和文本。

自定义控件

如果您想创建一个需要额外(可绑定)属性的 ToggleButton,您可以基于 ToggleButton 类型创建一个具有图像和文本依赖属性的自定义控件。创建一个派生自 ToggleButton.

的新类型 AdvancedToggleButton
public class AdvancedToggleButton : ToggleButton
{
   static AdvancedToggleButton()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(AdvancedToggleButton), new FrameworkPropertyMetadata(typeof(AdvancedToggleButton)));
   }

   public ImageSource ImageSource
   {
      get => (ImageSource) GetValue(ImageSourceProperty);
      set => SetValue(ImageSourceProperty, value);
   }

   public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
      nameof(ImageSource), typeof(ImageSource), typeof(AdvancedToggleButton));

   public string FirstText
   {
      get => (string) GetValue(FirstTextProperty);
      set => SetValue(FirstTextProperty, value);
   }

   public static readonly DependencyProperty FirstTextProperty = DependencyProperty.Register(
      nameof(FirstText), typeof(string), typeof(AdvancedToggleButton));

   public string SecondText
   {
      get => (string) GetValue(SecondTextProperty);
      set => SetValue(SecondTextProperty, value);
   }

   public static readonly DependencyProperty SecondTextProperty = DependencyProperty.Register(
      nameof(SecondText), typeof(string), typeof(AdvancedToggleButton));
}

然后您可以在您的应用程序资源或范围内的另一个资源字典中创建默认隐式样式(通过省略 x:Key),以便自动应用该样式。

<Style TargetType="{x:Type local:AdvancedToggleButton}">

   <Setter Property="Background"
           Value="#32353B" />
   <Setter Property="Margin"
           Value="10,5" />
   <Setter Property="Height"
           Value="45" />
   <Setter Property="BorderThickness"
           Value="0" />
   <Setter Property="Padding"
           Value="1" />
   <Setter Property="HorizontalAlignment"
           Value="Stretch" />

   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:AdvancedToggleButton}">
            <StackPanel>
               <Border BorderBrush="{TemplateBinding BorderBrush}"
                       Background="{TemplateBinding Background}">
                  <StackPanel Orientation="Horizontal"
                              HorizontalAlignment="Left"
                              Margin="0">
                     <ContentPresenter HorizontalAlignment="Left"
                                       VerticalAlignment="Center" />

                     <Image Source="{TemplateBinding ImageSource}"
                            HorizontalAlignment="Left"
                            Stretch="Uniform"
                            Width="45"
                            IsEnabled="True" />

                     <StackPanel Margin="2">
                        <TextBlock Foreground="#DCDDDE"
                                   FontSize="18"
                                   FontFamily="Arial"
                                   Text="{TemplateBinding FirstText}"/>
                        <TextBlock Foreground="#52555C"
                                   FontSize="12"
                                   FontFamily="Arial"
                                   Text="{TemplateBinding SecondText}"/>
                     </StackPanel>
                  </StackPanel>
               </Border>
            </StackPanel>

         </ControlTemplate>

      </Setter.Value>
   </Setter>
   <Style.Triggers>
      <Trigger Property="IsChecked"
               Value="True">
         <Setter Property="Background"
                 Value="#282B2E" />
      </Trigger>

      <Trigger Property="IsMouseOver"
               Value="True">
         <Setter Property="Background">
            <Setter.Value>
               <SolidColorBrush Color="#FF282B2E"
                                Opacity="0.5" />
            </Setter.Value>
         </Setter>
      </Trigger>

   </Style.Triggers>
</Style>

请注意,我删除了 HorizontalAlignment 的重复项 setter。 Image 将其 Source 绑定到 ImageSource 属性,TextBlock 分别绑定到 FirstTextSecondText。您可以在 XAML 或代码中定义 AdvancedToggleButton

<local:AdvancedToggleButton ImageSource="\Resources/Check.jpg"
                            FirstText="Strona"
                            SecondText="Login"/>
RadioButton radioButton = new RadioButton();
radioButton.GroupName = "Side";
radioButton.ImageSource = new BitmapImage(new Uri("https://www.google.com/favicon.ico"));
radioButton.FirstText = "Strona";
radioButton.SecondText = "Login"

关于自定义控件的有用资源:

附加属性

另一种不创建自定义控件的替代方法是创建一组附加属性。

public static class ToggleButtonProperties
{
   public static ImageSource GetImageSource(DependencyObject dependencyObject)
   {
      return (ImageSource) dependencyObject.GetValue(ImageSourceProperty);
   }

   public static void SetImageSource(DependencyObject dependencyObject, ImageSource value)
   {
      dependencyObject.SetValue(ImageSourceProperty, value);
   }

   public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.RegisterAttached(
      "ImageSource", typeof(ImageSource), typeof(ToggleButtonProperties));

   public static string GetFirstText(DependencyObject dependencyObject)
   {
      return (string) dependencyObject.GetValue(FirstTextProperty);
   }

   public static void SetFirstText(DependencyObject dependencyObject, string value)
   {
      dependencyObject.SetValue(FirstTextProperty, value);
   }

   public static readonly DependencyProperty FirstTextProperty = DependencyProperty.RegisterAttached(
      "FirstText", typeof(string), typeof(ToggleButtonProperties));

   public static string GetSecondText(DependencyObject dependencyObject)
   {
      return (string) dependencyObject.GetValue(SecondTextProperty);
   }

   public static void SetSecondText(DependencyObject dependencyObject, string value)
   {
      dependencyObject.SetValue(SecondTextProperty, value);
   }

   public static readonly DependencyProperty SecondTextProperty = DependencyProperty.RegisterAttached(
      "SecondText", typeof(string), typeof(ToggleButtonProperties));
}

这些属性可以在控件模板中使用括号绑定,即 binding syntax for attached propertiesRelativeSource 到父 ToggleButton.

<Style x:Key="ToggleButton_Chose" TargetType="{x:Type ToggleButton}">

   <Setter Property="Background"
           Value="#32353B" />
   <Setter Property="Margin"
           Value="10,5" />
   <Setter Property="Height"
           Value="45" />
   <Setter Property="BorderThickness"
           Value="0" />
   <Setter Property="Padding"
           Value="1" />
   <Setter Property="HorizontalAlignment"
           Value="Stretch" />

   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type ToggleButton}">
            <StackPanel>
               <Border BorderBrush="{TemplateBinding BorderBrush}"
                       Background="{TemplateBinding Background}">
                  <StackPanel Orientation="Horizontal"
                              HorizontalAlignment="Left"
                              Margin="0">
                     <ContentPresenter HorizontalAlignment="Left"
                                       VerticalAlignment="Center" />

                     <Image Source="{Binding (local:ToggleButtonProperties.ImageSource), RelativeSource={RelativeSource TemplatedParent}}"
                            HorizontalAlignment="Left"
                            Stretch="Uniform"
                            Width="45"
                            IsEnabled="True" />

                     <StackPanel Margin="2">
                        <TextBlock Foreground="#DCDDDE"
                                   FontSize="18"
                                   FontFamily="Arial"
                                   Text="{Binding (local:ToggleButtonProperties.FirstText), RelativeSource={RelativeSource TemplatedParent}}"/>
                        <TextBlock Foreground="#52555C"
                                   FontSize="12"
                                   FontFamily="Arial"
                                   Text="{Binding (local:ToggleButtonProperties.SecondText), RelativeSource={RelativeSource TemplatedParent}}"/>
                     </StackPanel>
                  </StackPanel>
               </Border>
            </StackPanel>

         </ControlTemplate>

      </Setter.Value>
   </Setter>
   <Style.Triggers>
      <Trigger Property="IsChecked"
               Value="True">
         <Setter Property="Background"
                 Value="#282B2E" />
      </Trigger>

      <Trigger Property="IsMouseOver"
               Value="True">
         <Setter Property="Background">
            <Setter.Value>
               <SolidColorBrush Color="#FF282B2E"
                                Opacity="0.5" />
            </Setter.Value>
         </Setter>
      </Trigger>

   </Style.Triggers>
</Style>

分配或绑定附加属性是通过静态 class.

<ToggleButton Style="{StaticResource ToggleButton_Chose}"
              local:ToggleButtonProperties.ImageSource="\Resources/Check.jpg"
              local:ToggleButtonProperties.FirstText="Strona"
              local:ToggleButtonProperties.SecondText="Login"/>
RadioButton radioButton = new RadioButton();
radioButton.GroupName = "Side";
ToggleButtonProperties.SetImageSource(radioButton, new BitmapImage(new Uri("https://www.google.com/favicon.ico")));
ToggleButtonProperties.SetFirstText(radioButton, "Strona");
ToggleButtonProperties.SetSecondText(radioButton, "Login");

有关附加属性的有用资源:

But is ther any other method to sett this? I will have around 100 of the RadioButtons and any of there should get other image and text.

创建一个简单的数据类型:

    public class ButtonContent
    {
        public string Strona { get; set; }
        public string Login { get; set; }
        public object ImageSource { get; set; }
    }

此类型将用于将按钮数据传递到上下文中。
因此,我们稍微改变一下样式:

        <Style x:Key="ToggleButton_Chose" TargetType="{x:Type ToggleButton}" >

            <Setter Property="Background" Value="#32353B" />
            <Setter Property="Margin" Value="10,5"/>
            <Setter Property="Height" Value="45" />
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="Padding" Value="1" />
            <Setter Property="HorizontalAlignment" Value="Stretch"/>

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                        <StackPanel>
                            <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            Background="{TemplateBinding Background}">
                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0">
                                    <ContentPresenter HorizontalAlignment="Left"                  
                                          VerticalAlignment="Center"/>

                                    <Image Source="{Binding ImageSource}"
                                           HorizontalAlignment="Left" Stretch="Uniform" Width="45" IsEnabled="True" />

                                    <StackPanel Margin="2">
                                        <TextBlock Foreground="#DCDDDE"  FontSize="18" FontFamily="Arial"
                                                   Text="{Binding Strona}"/>
                                        <TextBlock Foreground="#52555C"  FontSize="12" FontFamily="Arial"
                                                   Text="{Binding Login}"/>
                                    </StackPanel>
                                </StackPanel>
                            </Border>
                        </StackPanel>

                    </ControlTemplate>

                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter Property="Background" Value="#282B2E"/>
                </Trigger>

                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background">
                        <Setter.Value>
                            <SolidColorBrush Color="#FF282B2E" Opacity="0.5"/>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>

对于一组按钮,使用 ItemsControl:

        <DataTemplate x:Key="itemTemplate" DataType="{x:Type local:ButtonContent}">
            <ToggleButton Style="{DynamicResource ToggleButton_Chose}"/>
        </DataTemplate>
        <ItemsControl x:Name="itemsControl"
                      ItemTemplate="{DynamicResource itemTemplate}">
        </ItemsControl>

创建一个包含数据的可观察集合并将其传递给 ItemsControl 源:

    public partial class MainWindow : Window
    {
        private readonly ObservableCollection<ButtonContent> ButtonContents
            = new ObservableCollection<ButtonContent>();
        public MainWindow()
        {
            InitializeComponent();
            itemsControl.ItemsSource = ButtonContents;
            ButtonContents.Add(new ButtonContent() { Strona = "Strona1", Login = "Login1", ImageSource = "Image/block.png" });
            ButtonContents.Add(new ButtonContent() { Strona = "Strona2", Login = "Login2", ImageSource = "Image/block.png" });
            ButtonContents.Add(new ButtonContent() { Strona = "Strona3", Login = "Login3", ImageSource = "Image/block.png" });
            ButtonContents.Add(new ButtonContent() { Strona = "Strona4", Login = "Login4", ImageSource = "Image/block.png" });
        }

    }