WPF自定义控件01:FlatButton

简介: 主要介绍一下WPF如何实现自定义控件,通过继承Button控件,和自定义样式来实现Flat样式的漂亮Button。虽然这个FlatButton也可以通过内置的样式达到同样的效果,但自定义控件可以更好的封装和重用,使用起来更加的方便。

1 WPF概述


     根据百度百科,WPF是Windows Presentation Foundation的缩写,它是微软推出的基于Windows 的新一代UI框架,属于.NET Framework 3.0+的一部分。WPF提供了统一的编程模型、语言和框架,真正做到了UI与逻辑的分离,同时也提供了全新的多媒体交互用户图形界面。借助WPF,可以让开发人员开发出绚丽的应用程序。

     环境准备:Visual Studio 2019社区版(免费);.NET FrameWork 5 。

2 WPF项目创建


     首先需要利用Visual Studio 2019社区版创建一个新的WPF桌面应用WpfControls和一个新的WPF控件库项目Yd.WpfControls。并在WpfControls项目中添加对Yd.WpfControls项目的引用。具体如下所示

0.jpg

此项目中,已经创建了一些文件,下面将分重点进行说明。

3 自定义控件FlatButton


第一步,定义一些基础的类,其中有字体的设置FlatFonts.cs,其代码如下:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading.Tasks;
usingSystem.Windows.Media;
namespaceYd.WpfControls{
publicclassFlatFonts    {
publicstaticFontFamilycontentFontFamily=newFontFamily("Microsoft YaHei");
publicstaticdoublecontentFontSize=16D;
    }
}

其中就是定义了一个默认的字体和字号,注意字号是double类型的。同样的,下面给出颜色的定义,FlatColors.cs示例代码如下:

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Windows.Media;
namespaceYd.WpfControls{
publicclassFlatColors    {
//https://flatuicolors.com/palette/defopublicstaticBrushTUROUOISE=newSolidColorBrush( Color.FromRgb(26, 188, 156));
publicstaticBrushEMERALD=newSolidColorBrush(Color.FromRgb(46, 204, 113));
publicstaticBrushPETER_RIVER=newSolidColorBrush(Color.FromRgb(52, 152, 219));
publicstaticBrushBELIZE_HOLE=newSolidColorBrush(Color.FromRgb(41, 128, 185));
publicstaticBrushMIDNIGHT_BLUE=newSolidColorBrush(Color.FromRgb(44, 62, 80));
publicstaticBrushCLOUDS=newSolidColorBrush(Color.FromRgb(236, 240, 241));
    }
}

注意:颜色是来自Flat UI Color系列的网站,且颜色定义的类型的Brush,而不是Color。下面再给出FlatButton的Type定义,FlatButtonType.cs示例代码如下:

namespaceYd.WpfControls{
publicenumFlatButtonType    {
Default,
Warn,
Danger    }
}

第二步,创建一个自定义控件,他会自动创建一个样式Generic.xaml,这个是默认的控件样式定义的文件。创建的界面如下:

1(8).jpg

修改文件名为FlatButton,并继承自Button控件,FlatButton.cs示例代码如下:

usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Media;
namespaceYd.WpfControls{
publicclassFlatButton : Button    {
staticFlatButton()
        {
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatButton), 
newFrameworkPropertyMetadata(typeof(FlatButton)));
        }
//自定义控件属性ButtonType,其DependencyProperty为ButtonType+PropertypublicstaticreadonlyDependencyPropertyButtonTypeProperty=DependencyProperty.Register("ButtonType", typeof(FlatButtonType), typeof(FlatButton), 
newPropertyMetadata(FlatButtonType.Default));
publicFlatButtonTypeButtonType        {
get { return (FlatButtonType)GetValue(ButtonTypeProperty); }
set { SetValue(ButtonTypeProperty, value); }
        }
publicstaticreadonlyDependencyPropertyMouseOverBackgroundProperty=DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(FlatButton),
newPropertyMetadata(Brushes.RoyalBlue));
publicBrushMouseOverBackground        {
get { return (Brush)GetValue(MouseOverBackgroundProperty); }
set { SetValue(MouseOverBackgroundProperty, value); }
        }
publicstaticreadonlyDependencyPropertyMouseOverForegroundProperty=DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(FlatButton),
newPropertyMetadata(Brushes.White));
publicBrushMouseOverForeground        {
get { return (Brush)GetValue(MouseOverForegroundProperty); }
set { SetValue(MouseOverForegroundProperty, value); }
        }
publicstaticreadonlyDependencyPropertyCornerRadiusProperty=DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(FlatButton),
newPropertyMetadata(newCornerRadius(2)));
publicCornerRadiusCornerRadius        {
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
        }
    }
}

FlatButton的UI定义基本都是靠样式定义文件FlatButton.xaml,其类似于CSS,但是语法描述不同。FlatButton.xaml位于Style目录下,其示例代码如下:

<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Yd.WpfControls"><StyleTargetType="{x:Type local:FlatButton}"><SetterProperty="FontSize"Value="{x:Static local:FlatFonts.contentFontSize}"/><SetterProperty="FontFamily"Value="{x:Static local:FlatFonts.contentFontFamily}"/><Style.Triggers><TriggerProperty="ButtonType"Value="Default"><SetterProperty="Background"Value="{x:Static local:FlatColors.PETER_RIVER}"/><SetterProperty="Foreground"Value="{x:Static local:FlatColors.CLOUDS}"/><SetterProperty="MouseOverBackground"Value="{x:Static local:FlatColors.BELIZE_HOLE}"/><SetterProperty="MouseOverForeground"Value="{x:Static local:FlatColors.CLOUDS}"/><SetterProperty="BorderBrush"Value="Transparent"/><SetterProperty="BorderThickness"Value="0"/><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Type local:FlatButton}"><Borderx:Name="border"Background="{TemplateBinding Background}"CornerRadius="{TemplateBinding CornerRadius}"BorderThickness="{TemplateBinding BorderThickness}"Width="{TemplateBinding Width}"Height="{TemplateBinding Height}"SnapsToDevicePixels="True"><TextBlockx:Name="text"Text="{TemplateBinding Content}"Foreground="{TemplateBinding Foreground}"VerticalAlignment="Center"HorizontalAlignment="Center"/></Border><ControlTemplate.Triggers><TriggerProperty="IsMouseOver"Value="True"><SetterTargetName="border"Property="Background"Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/><SetterTargetName="text"Property="Foreground"Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Trigger><TriggerProperty="ButtonType"Value="Warn"><SetterProperty="Background"Value="#f1c40f"/><SetterProperty="MouseOverBackground"Value="#f39c12"/><SetterProperty="Foreground"Value="{x:Static local:FlatColors.CLOUDS}"/><SetterProperty="MouseOverForeground"Value="#ecf0f1"/><SetterProperty="BorderBrush"Value="Transparent"/><SetterProperty="BorderThickness"Value="0"/><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Type local:FlatButton}"><Borderx:Name="border"Background="{TemplateBinding Background}"CornerRadius="{TemplateBinding CornerRadius}"BorderThickness="{TemplateBinding BorderThickness}"Width="{TemplateBinding Width}"Height="{TemplateBinding Height}"SnapsToDevicePixels="True"><TextBlockx:Name="text"Text="{TemplateBinding Content}"Foreground="{TemplateBinding Foreground}"VerticalAlignment="Center"HorizontalAlignment="Center"/></Border><ControlTemplate.Triggers><TriggerProperty="IsMouseOver"Value="True"><SetterTargetName="border"Property="Background"Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/><SetterTargetName="text"Property="Foreground"Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Trigger><TriggerProperty="ButtonType"Value="Danger"><SetterProperty="Background"Value="#c0392b"/><SetterProperty="MouseOverBackground"Value="#e74c3c"/><SetterProperty="Foreground"Value="{x:Static local:FlatColors.CLOUDS}"/><SetterProperty="MouseOverForeground"Value="#ecf0f1"/><SetterProperty="BorderBrush"Value="Transparent"/><SetterProperty="BorderThickness"Value="0"/><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Type local:FlatButton}"><Borderx:Name="border"Background="{TemplateBinding Background}"CornerRadius="{TemplateBinding CornerRadius}"BorderThickness="{TemplateBinding BorderThickness}"Width="{TemplateBinding Width}"Height="{TemplateBinding Height}"SnapsToDevicePixels="True"><TextBlockx:Name="text"Text="{TemplateBinding Content}"Foreground="{TemplateBinding Foreground}"VerticalAlignment="Center"HorizontalAlignment="Center"/></Border><ControlTemplate.Triggers><TriggerProperty="IsMouseOver"Value="True"><SetterTargetName="border"Property="Background"Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/><SetterTargetName="text"Property="Foreground"Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Trigger></Style.Triggers></Style></ResourceDictionary>

此样式定义中,首先需要明确样式是针对哪个控件的,其用如下命令指定:

<StyleTargetType="{x:Type local:FlatButton}">

local这个命名空间是在 xmlns:local="clr-namespace:Yd.WpfControls" 进行定义的,这个需要手动添加,否则内部找不到FlatButton空间。在样式表中,可以对属性进行绑定,其中的属性可以是自定义的属性,比如:

<TriggerProperty="ButtonType"Value="Default">

也可以绑定到静态类对象中,比如前面定义的颜色笔刷和字体对象,如:

<SetterProperty="Background"Value="{x:Static local:FlatColors.PETER_RIVER}"/><SetterProperty="FontSize"Value="{x:Static local:FlatFonts.contentFontSize}"/><SetterProperty="FontFamily"Value="{x:Static local:FlatFonts.contentFontFamily}"/>

第三步,将样式FlatButton.xaml添加到默认的Generic.xaml中,否则则UI无法加载样式定义信息Generic.xaml其代码如下:

<ResourceDictionaryxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Yd.WpfControls"><ResourceDictionary.MergedDictionaries><ResourceDictionarySource="/Yd.WpfControls;component/Style/FlatButton.xaml"/></ResourceDictionary.MergedDictionaries></ResourceDictionary>

注意:ResourceDictionary Source的定义中,/Yd.WpfControls;component/+样式表路径,这个前缀不可少。

第四步,编译后,可以将自定义控件添加到UI界面上,如下所示:

0.jpg

选中某个FlatButton控件,可以在属性窗口中进行属性设置,其中也包含自定义的属性,示例如下:

1(8).jpg

主界面窗口的示例代码如下:

<Windowxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:WpfControls="clr-namespace:Yd.WpfControls;assembly=Yd.WpfControls"x:Class="WpfControls.MainWindow"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Grid><WpfControls:FlatButtonContent="确定"HorizontalAlignment="Left"Height="37"Margin="89,83,0,0"VerticalAlignment="Top"ButtonType="Default"CornerRadius="18"Width="120"FontFamily="Microsoft YaHei"FontSize="16"/><WpfControls:FlatButtonContent="取消"HorizontalAlignment="Left"Margin="412,88,0,0"VerticalAlignment="Top"Height="32"ButtonType="Warn"CornerRadius="18"Width="120"FontFamily="Microsoft YaHei"FontSize="16"Click="FlatButton_Click"/><WpfControls:FlatButtonContent="删除"HorizontalAlignment="Left"Margin="249,88,0,0"VerticalAlignment="Top"Height="32"ButtonType="Danger"CornerRadius="0"Width="120"x:Name="btn01"FontFamily="Microsoft YaHei"FontSize="16"/><WpfControls:FlatButtonContent="FlatButton"HorizontalAlignment="Left"Margin="72,0,0,0"VerticalAlignment="Center"Height="37"Width="137"/></Grid></Window>

第五步,编译运行,主界面如下:

0.jpg

相关文章
WPF自定义控件05:ToggleButton
本文重点介绍WPF中如何实现自定义ToggleButton控件,它是一个开关控件,通过单击来进行状态的快速切换。
5083 0
WPF自定义控件05:ToggleButton
|
人工智能 C#
WPF自定义控件库之Window窗口
本文以自定义窗口为例,简述WPF开发中如何通过自定义控件来扩展功能和样式,仅供学习分享使用,如有不足之处,还请指正。
246 5
|
XML C# 数据格式
WPF中用户控件和自定义控件
无论是在WPF中还是WinForm中,都有用户控件(UserControl)和自定义控件(CustomControl),这两种控件都是对已有控件的封装,实现功能重用。但是两者还是有一些区别,本文对这两种控件进行讲解。
|
数据可视化 前端开发 C#
WPF自定义控件的三种方式
某些场景下,我们确实需要创建新的控件。此时,理解 WPF不同控件的创建方法就显得非常重要。 WPF 提供3个用于创建控件的方法,每个方法都提供不同的灵活度。
892 1
WPF自定义控件的三种方式
|
C# 容器
WPF自定义控件10:FlatListView
在不少的应用程序中,有时候需要使用ListView控件来显示一组集合数据,这样可以从一组数据中进行选择,让数据更加的规范,便于统计和分析。本文将介绍一下自定义的列表控件FlatListView,它与FlatCheckBox实现过程非常类似,它是继承自ListView,但使用自定义的UI样式来美化界面。
581 0
WPF自定义控件10:FlatListView
WPF自定义控件09:FlatWaveButton
按钮在很多应用程序中都是必不可少的控件,如果给按钮控件添加一些动画效果,比如单击它后会显示一个水波纹扩散的动画效果,那么感觉上更加的高级。本文将介绍一下自定义水波纹按钮控件FlatWaveButton,它是一个UserControl(FlatButton)控件,自身携带UI样式和后台逻辑。
654 0
WPF自定义控件09:FlatWaveButton
|
Web App开发 C#
WPF自定义控件08:FlatRoundImage
在不少的应用程序中,用户中心的个人页面经常需要显示头像,这个当前主流的做法就是用户上传一个图片,系统进行截取并显示为一个圆形的轮廓,即圆形的照片。本文将介绍一下自定义的图片控件FlatRoundImage,它是一个UserControl控件,自身携带UI样式和后台逻辑。
653 0
WPF自定义控件08:FlatRoundImage
WPF自定义控件07:FlatTextBox
本文将介绍一下自定义的文本框控件FlatTextBox,它与FlatCheckBox实现过程非常类似,它是继承自TextBox,但使用自定义的UI样式来美化界面,并添加了特有的一些依赖属性。
538 0
WPF自定义控件07:FlatTextBox
WPF自定义控件06:FlatComboBox
在不少的应用程序中,经常需要使用下拉框(ComboBox)控件来从类别字段中选择,这样可以限定值的范围,让数据更加的规范,便于统计和分析。本文将介绍一下自定义的下拉框控件FlatComboBox,它与FlatCheckBox实现过程非常类似,它是继承自ComboBox,但使用自定义的UI样式来美化界面。下面将详细介绍具体的实现细节。
835 0
WPF自定义控件06:FlatComboBox
WPF自定义控件04:FlatRadioButton
本文通过在WPF中引入Font Awesome图标字体来实现自定义FlatRadioButton控件的UI绘图。用户只需要在窗体上引入自定义的FlatRadioButton控件即可使用具有Flat UI效果的控件,非常方便。
610 0
WPF自定义控件04:FlatRadioButton