假设需要实现一个图标和文本结合的按钮 ,普通做法是 直接重写该按钮的模板;
如果想作为通用的呢?
两种做法:
- 附加属性
- 自定义控件
推荐使用附加属性的形式
第一种:附加属性
创建Button的附加属性 ButtonExtensions
public static class ButtonExtensions
{
// Using a DependencyProperty as the backing store for IconWidth. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IconWidthProperty =
DependencyProperty.RegisterAttached("IconWidth", typeof(int), typeof(ButtonExtensions), new PropertyMetadata(0));
public static int GetIconWidth(DependencyObject obj)
{
return (int)obj.GetValue(IconWidthProperty);
}
public static void SetIconWidth(DependencyObject obj, int value)
{
obj.SetValue(IconWidthProperty, value);
}
// Using a DependencyProperty as the backing store for IconHeight. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IconHeightProperty =
DependencyProperty.RegisterAttached("IconHeight", typeof(int), typeof(ButtonExtensions), new PropertyMetadata(0));
public static int GetIconHeight(DependencyObject obj)
{
return (int)obj.GetValue(IconHeightProperty);
}
public static void SetIconHeight(DependencyObject obj, int value)
{
obj.SetValue(IconHeightProperty, value);
}
// Using a DependencyProperty as the backing store for IconGeometry. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IconGeometryProperty =
DependencyProperty.RegisterAttached("IconGeometry", typeof(Geometry), typeof(ButtonExtensions), new PropertyMetadata((object)null));
public static Geometry GetIconGeometry(DependencyObject obj)
{
return (Geometry)obj.GetValue(IconGeometryProperty);
}
public static void SetIconGeometry(DependencyObject obj, Geometry value)
{
obj.SetValue(IconGeometryProperty, value);
}
}
样式
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:coreHelper="clr-namespace:NeonGenesis.Core.AttachedProperties;assembly=NeonGenesis.Core">
<Style x:Key="ButtonVerBase" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="10,5" />
<Setter Property="FrameworkElement.Cursor" Value="Hand" />
<Setter Property="UIElement.SnapsToDevicePixels" Value="True" />
<Setter Property="coreHelper:ButtonExtensions.IconHeight" Value="24" />
<Setter Property="coreHelper:ButtonExtensions.IconWidth" Value="24" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border
Name="border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<Grid>
<StackPanel
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Orientation="Vertical">
<Path
Name="pathIcon"
Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(coreHelper:ButtonExtensions.IconWidth)}"
Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(coreHelper:ButtonExtensions.IconHeight)}"
Margin="0,0,0,5"
Data="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=(coreHelper:ButtonExtensions.IconGeometry)}"
Fill="{TemplateBinding Foreground}"
Stretch="Uniform" />
<ContentPresenter
Name="contentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Focusable="False"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="coreHelper:ButtonExtensions.IconGeometry" Value="{x:Null}">
<Setter TargetName="pathIcon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="Content" Value="{x:Null}">
<Setter TargetName="pathIcon" Property="Margin" Value="0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
使用示例
<Button
Width="80"
Height="80"
coreHelper:ButtonExtensions.IconGeometry="{StaticResource RunningGeometry}"
coreHelper:ButtonExtensions.IconHeight="40"
coreHelper:ButtonExtensions.IconWidth="40"
Background="#1e90ff"
Content="运行"
Foreground="White"
Style="{StaticResource ButtonVerBase}" />
RunningGeometry为
<PathGeometry x:Key="RunningGeometry">M41.355947 0h572.962133a41.355947 41.355947 0 0 1 41.355947 41.355947v100.037973H0V41.355947A41.355947 41.355947 0 0 1 41.355947 0zM0 210.356907v772.287146A41.355947 41.355947 0 0 0 41.355947 1024h941.288106A41.355947 41.355947 0 0 0 1024 982.644053V210.356907z m851.88608 295.867733L581.973333 776.137387a47.786667 47.786667 0 0 1-66.710186 0.832853 47.786667 47.786667 0 0 1-7.796054-6.294187l-115.083946-115.0976-120.54528 120.558934a47.786667 47.786667 0 0 1-67.611307 0 47.786667 47.786667 0 0 1 0-67.611307l147.12832-147.12832a48.237227 48.237227 0 0 1 13.653333-9.557333 47.786667 47.786667 0 0 1 62.887254 4.096l119.6032 119.507626 236.776106-236.817066a47.786667 47.786667 0 0 1 67.611307 0 47.786667 47.786667 0 0 1 0 67.597653z</PathGeometry>
效果
第二种:自定义控件
后续更新