问题描述
我有一个带有 RadioButton
和 2 个 Image
的自定义 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
类型的图像和文本的依赖属性。创建一个派生自 AdvancedToggleButton
的新类型 ToggleButton
。
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(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
分别绑定到 FirstText
和 SecondText
。您可以在 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(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(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(ToggleButtonProperties));
}
可以使用括号将这些属性绑定到控件模板中,即binding syntax for attached properties 和RelativeSource
到父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>
分配或绑定附加属性是通过静态类完成的。
<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");
关于附加属性的有用资源:
,但是还有其他方法可以设置吗?我将有大约 100 个 RadioButtons,其中任何一个都应该得到其他图像和文本。
创建一个简单的数据类型:
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" });
}
}