我想在我的应用程序中添加几个自定义按钮,其中包含用于单击和悬停的图标和简单样式(一个模板适用于所有按钮,但图标、颜色等不同)。图标应在悬停并单击时改变颜色。哪种方法最有效?
我考虑了一些自定义控件或每个按钮的单独样式。
您只需为图标定义一个附加属性并声明一个尊重该附加属性的按钮模板。这很简单:
附带财产:
internal static class IconProperties
{
#region Data
private const string IconPropertyName = "Icon";
public static readonly DependencyProperty IconProperty =
DependencyProperty.RegisterAttached(IconPropertyName,
typeof(Geometry),
typeof(IconProperties),
new(default(Geometry)));
public static void SetIcon(DependencyObject o, Geometry value)
=> o.SetValue(IconProperty, value);
public static Geometry GetIcon(DependencyObject o)
=> (Geometry)o.GetValue(DataProperty);
#endregion
#region Height
private const string HeightPropertyName = "Height";
public static readonly DependencyProperty HeightProperty =
DependencyProperty.RegisterAttached(HeightPropertyName,
typeof(double),
typeof(IconProperties),
new(default(double)));
public static void SetHeight(DependencyObject o, double value)
=> o.SetValue(HeightProperty, value);
public static double GetHeight(DependencyObject o)
=> (double)o.GetValue(HeightProperty);
#endregion
#region Width
private const string WidthPropertyName = "Width";
public static readonly DependencyProperty WidthProperty =
DependencyProperty.RegisterAttached(WidthPropertyName,
typeof(double),
typeof(IconProperties),
new(default(double)));
public static void SetWidth(DependencyObject o, double value)
=> o.SetValue(WidthProperty, value);
public static double GetWidth(DependencyObject o)
=> (double)o.GetValue(WidthProperty);
#endregion
#region Margin
private const string MarginPropertyName = "Margin";
public static readonly DependencyProperty MarginProperty =
DependencyProperty.RegisterAttached(MarginPropertyName,
typeof(Thickness),
typeof(IconProperties),
new(default(Thickness)));
public static void SetMargin(DependencyObject o, Thickness value)
=> o.SetValue(MarginProperty, value);
public static Thickness GetMargin(DependencyObject o)
=> (Thickness)o.GetValue(MarginProperty);
#endregion
}
按钮模板:
<Border x:Name="Root"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Viewbox Height="{Binding Path=(ap:IconProperties.Height), RelativeSource={RelativeSource Mode=TemplatedParent}}"
Margin="{Binding Path=(ap:IconProperties.Margin), RelativeSource={RelativeSource Mode=TemplatedParent}}"
Stretch="Uniform"
Width="{Binding Path=(ap:IconProperties.Width), RelativeSource={RelativeSource Mode=TemplatedParent}}">
<Path x:Name="Icon"
Data="{Binding Path=(ap:IconProperties.Data), RelativeSource={RelativeSource Mode=TemplatedParent}}"
Fill="{TemplateBinding Foreground}"/>
</Viewbox>
<TextBlock x:Name="TextContent"
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
这里省略了很多细节,因为它们不是那么重要。要为按钮设置动画,您可以使用
VisualStateManager
,还可以为图标定义更多属性,例如不透明度、对齐像素等。
拥有附加属性和模板后,用法将非常基本:
<Button Template="{StaticResource MyAwesomeTempalte}"
nsWithAttachedProperties:IconProperties.Data="{StaticResource MyAwesomeIcon}"/>