WPF自定义按钮,增加圆角样式功能!
一、自定义控件库流程(以添加圆角属性为例)
1.创建控件库项目
- 新建工程后,默认会有“Themes”文件加,用于保存控件样式。
- 右键项目选择添加新建项=> 选择WPF => 选择自定义控件(WPF)=> 输入控件名然后电机添加,创建控件。
- 右键项目选择添加资源字典(WPF)=> 输入控件名然后电机添加,创建资源字典。
- 创建完毕后的框架如下图:
2.控件.cs文件中添加边框圆角属性
public class MyButton : Button
{
static MyButton()
{
// 新创建的控件名 模板名,资源字典(如MyButton.xaml),如果要跟旧的一样,直接填“Button”
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton), new FrameworkPropertyMetadata(typeof(MyButton)));
}
/// <summary>
/// 按键圆角属性委托
/// CornerRadius:用于调用的委托名字
/// typeof(MyButton):指定控件
/// </summary>
public static readonly DependencyProperty BorderRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata());
/// <summary>
/// 定义按钮圆角属性
/// </summary>
public int CornerRadius
{
get { return (int)GetValue(BorderRadiusProperty); }
set { SetValue(BorderRadiusProperty, value); }
}
}
3.调用按键资源文件
Generic.xaml中增加如下代码,调用资源文件MyButton.xaml
<ResourceDictionary.MergedDictionaries>
<!--引用按键资源字典-->
<ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/MyButton.xaml"/>
</ResourceDictionary.MergedDictionaries>
4.编辑MyButton.xaml文件,设置样式
vs默认的样式请参考:
添加颜色资源
因为我将通用颜色
<!--引用颜色资源-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/ColorResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
设置默认样式
//将设置默认添加时的样式
<Style TargetType="local:MyButton">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="23" />
<Setter Property="MinWidth" Value="75" />
//...后续代码
绑定边框样式数据
在边框属性中,将边框的属性对控件属性进行绑定
其中:
CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}",中的CornerRadius 对应.cs文件中创建的委托名
其他属性直接调用的控件原来就有的属性
<Border TextBlock.Foreground="{TemplateBinding Foreground}"
x:Name="Border"
CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
//...
5.完整MyButton.xaml资源字典如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyWpfCustomControlLibrary"
xmlns:vsm="http://schemas.microsoft.com/netfx/2009/xaml/presentation">
<!--引用颜色资源-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source= "/MyWpfCustomControlLibrary;Component/Themes/ColorResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- FocusVisual -->
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="2"
StrokeThickness="1"
Stroke="#60000000"
StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Button -->
<Style TargetType="local:MyButton">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="MinHeight" Value="23" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border TextBlock.Foreground="{TemplateBinding Foreground}"
x:Name="Border"
CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.5" />
<VisualTransition GeneratedDuration="0"
To="Pressed" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource ControlMouseOverColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource ControlPressedColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[0].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource PressedBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource PressedBorderLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledForegroundColor}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).
(GradientBrush.GradientStops)[1].(GradientStop.Color)"
Storyboard.TargetName="Border">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledBorderDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RecognizesAccessKey="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDefault" Value="true">
<Setter TargetName="Border" Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource DefaultBorderBrushLightBrush}" Offset="0.0" />
<GradientStop Color="{DynamicResource DefaultBorderBrushDarkColor}" Offset="1.0" />
</GradientStopCollection>
</GradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
6.生成dll
点击生成=> 选择生成项目选项,生成
7.新项目调用
创建新项目,在新项目的引用项右键点击,添加引用
通过浏览,找到生成的.dll文件,然后将文件添加到系统中,然后系统工具箱会自动显示创建的控件,然后按照正常控件拖拽引用就可以。
拖拽引用后,xaml文件中会自动添加调用资源:
xmlns:MyWpfCustomControlLibrary="clr-namespace:MyWpfCustomControlLibrary;assembly=MyWpfCustomControlLibrary"
二、自定义ComboBox控件
1.自定义控件编辑模板
- 组合框样式:编辑ComboBoxStyle
- 下拉框样式:编辑ComboBoxItemStyle
2.注意事项汇总
自定义格式跨层级绑定外层控件的数据
使用查找绑定的方式绑定数据
CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type local:UdComboBox}}}"
自定义下拉框样式后出现绑定数据DisplayMemberPath属性无效的情况
这种情况是由于绑定格式时作为内容显示的ContentPresenter没有设置ContentTemplateSelector属性引起的,绑定该属性后解决问题
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"