自定义一个WPF的PathButton
一、背景
做项目时总是少不了Button,但是普通的Button大家都不喜欢用,总是想要自定义的Button,正好项目中用到不要边框的Button,并且是形状也是根据功能不同而变化的,并且窗口程序是会放大缩小的,如果用图片形式是会出现失真的,并且切换主题时没法变色,当然你可以用多个尺寸的图片,并且每个主题配一套图片,但是很麻烦。
二、实现
以设置按钮为例,当然这里的颜色可能和你需要的不一样,但是没关系是可以自定义的
思路是写一个Usercontrol,继承自Button,然会应用一个样式,这里不直接用样式而是用Usercontrol是因为加了几个DependencyProperty,这样就可以自定义颜色了
Xaml代码
1 <Button x:Class="PathButton.PathButton" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 Style="{DynamicResource PathButtonStyle}" 7 d:DesignHeight="300" 8 d:DesignWidth="300" 9 mc:Ignorable="d"> 10 <Button.Resources> 11 <Style x:Key="FocusVisual"> 12 <Setter Property="Control.Template"> 13 <Setter.Value> 14 <ControlTemplate> 15 <Rectangle Margin="2" 16 SnapsToDevicePixels="true" 17 Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" 18 StrokeDashArray="1 2" 19 StrokeThickness="1" /> 20 </ControlTemplate> 21 </Setter.Value> 22 </Setter> 23 </Style> 24 <Style x:Key="PathButtonStyle" 25 TargetType="{x:Type Button}"> 26 <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}" /> 27 <Setter Property="Background" Value="#00000000" /> 28 <Setter Property="BorderBrush" Value="#00000000" /> 29 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /> 30 <Setter Property="BorderThickness" Value="0,1,1,1" /> 31 <Setter Property="HorizontalContentAlignment" Value="Center" /> 32 <Setter Property="VerticalContentAlignment" Value="Center" /> 33 <Setter Property="Padding" Value="1" /> 34 <Setter Property="Template"> 35 <Setter.Value> 36 <ControlTemplate TargetType="{x:Type Button}"> 37 <Border x:Name="border" 38 Background="{TemplateBinding Background}" 39 BorderBrush="{TemplateBinding BorderBrush}" 40 BorderThickness="{TemplateBinding BorderThickness}" 41 SnapsToDevicePixels="true"> 42 <Path x:Name="Path" 43 Data="{Binding PathData}" 44 Fill="{Binding DefaultFillBrush}" 45 RenderTransformOrigin="0.5,0.5" 46 Stretch="Uniform" /> 47 </Border> 48 49 <ControlTemplate.Triggers> 50 <Trigger Property="IsDefaulted" Value="True"> 51 <Setter TargetName="Path" Property="Fill" Value="{Binding DefaultFillBrush}" /> 52 </Trigger> 53 <Trigger Property="IsMouseOver" Value="True"> 54 <Setter TargetName="Path" Property="Fill" Value="{Binding MouseOverBrush}" /> 55 </Trigger> 56 <Trigger Property="IsPressed" Value="True"> 57 <Setter TargetName="Path" Property="Fill" Value="{Binding IsPressedBrush}" /> 58 </Trigger> 59 <Trigger Property="IsEnabled" Value="False"> 60 <Setter TargetName="Path" Property="Fill" Value="{Binding IsEnabledBrush}" /> 61 </Trigger> 62 </ControlTemplate.Triggers> 63 </ControlTemplate> 64 </Setter.Value> 65 </Setter> 66 </Style> 67 </Button.Resources> 68 69 </Button>
后台代码
1 public partial class PathButton : Button 2 { 3 public Geometry PathData 4 { 5 get { return (Geometry)GetValue(PathDataProperty); } 6 set { SetValue(PathDataProperty, value); } 7 } 8 9 // Using a DependencyProperty as the backing store for PathData. This enables animation, styling, binding, etc... 10 public static readonly DependencyProperty PathDataProperty = 11 DependencyProperty.Register("PathData", typeof(Geometry), typeof(PathButton), new PropertyMetadata(new PathGeometry())); 12 13 public Brush DefaultFillBrush 14 { 15 get { return (Brush)GetValue(DefaultFillBrushProperty); } 16 set { SetValue(DefaultFillBrushProperty, value); } 17 } 18 19 // Using a DependencyProperty as the backing store for DefaultFillBrush. This enables animation, styling, binding, etc... 20 public static readonly DependencyProperty DefaultFillBrushProperty = 21 DependencyProperty.Register("DefaultFillBrush", typeof(Brush), typeof(PathButton), new PropertyMetadata(Brushes.DarkGray)); 22 23 public Brush MouseOverBrush 24 { 25 get { return (Brush)GetValue(MouseOverBrushProperty); } 26 set { SetValue(MouseOverBrushProperty, value); } 27 } 28 29 // Using a DependencyProperty as the backing store for MouseOverBrush. This enables animation, styling, binding, etc... 30 public static readonly DependencyProperty MouseOverBrushProperty = 31 DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(PathButton), new PropertyMetadata(Brushes.DeepSkyBlue)); 32 33 public Brush IsPressedBrush 34 { 35 get { return (Brush)GetValue(IsPressedBrushProperty); } 36 set { SetValue(IsPressedBrushProperty, value); } 37 } 38 39 // Using a DependencyProperty as the backing store for IsPressedBrush. This enables animation, styling, binding, etc... 40 public static readonly DependencyProperty IsPressedBrushProperty = 41 DependencyProperty.Register("IsPressedBrush", typeof(Brush), typeof(PathButton), new PropertyMetadata(Brushes.DodgerBlue)); 42 43 public Brush IsEnabledBrush 44 { 45 get { return (Brush)GetValue(IsEnabledBrushProperty); } 46 set { SetValue(IsEnabledBrushProperty, value); } 47 } 48 49 // Using a DependencyProperty as the backing store for IsEnabledBrush. This enables animation, styling, binding, etc... 50 public static readonly DependencyProperty IsEnabledBrushProperty = 51 DependencyProperty.Register("IsEnabledBrush", typeof(Brush), typeof(PathButton), new PropertyMetadata(Brushes.LightGray)); 52 53 public PathButton() 54 { 55 InitializeComponent(); 56 DataContext = this; 57 } 58 }
用法
<pathButton:PathButton x:Name="Button" Width="50" Height="50" PathData="M31.679651,15.723C22.841078,15.723 15.677,22.887022 15.677,31.724249 15.677,40.562878 22.841078,47.727002 31.679651,47.727002 40.518124,47.727002 47.682003,40.562878 47.682003,31.724249 47.682003,22.887022 40.518124,15.723 31.679651,15.723z M25.174641,0L30.947304,8.1649995 30.977009,8.163671C31.891628,8.1361193,32.811726,8.1617675,33.732849,8.2423577L34.116646,8.2807278 40.096367,0.5289996 49.181995,4.5158782 47.510448,14.236901 47.626137,14.339919C48.479649,15.11912,49.268909,15.955267,49.990528,16.839653L50.234638,17.14785 60.403648,15.836 64.007996,25.079203 55.322643,31.217757 55.324234,31.258986C55.34618,32.174153,55.314838,33.094563,55.22847,34.015755L55.226952,34.030385 63.345997,40.294331 59.359104,49.380002 49.249798,47.645153 49.143776,47.764214C48.695721,48.255009,48.228832,48.72456,47.744774,49.172226L47.324875,49.549786 48.723995,60.394425 39.48156,64 33.403603,55.403061 33.023663,55.43042C32.149929,55.481137,31.270197,55.483376,30.38839,55.435608L29.679308,55.383191 23.130268,63.875 14.041999,59.886834 15.844025,49.393521 15.71986,49.282948C15.207753,48.815411,14.718776,48.32737,14.253661,47.820706L13.803129,47.315312 3.612031,48.630002 0.0080004195,39.385499 8.0905037,33.673707 8.0481892,33.048829C7.9875851,31.908507,8.0095654,30.758269,8.1175261,29.606822L8.1191311,29.59272 0,23.328246 3.9867127,14.242 14.093521,15.978928 14.104487,15.966273C15.033746,14.935561,16.045525,13.997155,17.124784,13.156928L17.159048,13.131042 15.929999,3.6040602z" DefaultFillBrush="Red" MouseOverBrush="Yellow" IsPressedBrush="Blue" IsEnabledBrush="Black"/>
这样就完成了,你只需要给一个你Path就可以显示你想要的按钮了,如果想改变颜色就设置下3个Brush就可以
三、效果
默认样式 鼠标进入 鼠标按下
Tips:可以在 nuget 里搜索 PathButton 安装使用啦