WPF自定义控件01: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项目的引用。具体如下所示:
此项目中,已经创建了一些文件,下面将分重点进行说明。
3 自定义控件FlatButton
第一步,定义一些基础的类,其中有字体的设置FlatFonts.cs,其代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace Yd.WpfControls
{
public class FlatFonts
{
public static FontFamily contentFontFamily = new FontFamily("Microsoft YaHei");
public static double contentFontSize = 16D;
}
}
其中就是定义了一个默认的字体和字号,注意字号是double类型的。同样的,下面给出颜色的定义,FlatColors.cs示例代码如下:
using System;
using System.Collections.Generic;
using System.Windows.Media;
namespace Yd.WpfControls
{
public class FlatColors
{
//https://flatuicolors.com/palette/defo
public static Brush TUROUOISE = new SolidColorBrush( Color.FromRgb(26, 188, 156));
public static Brush EMERALD = new SolidColorBrush(Color.FromRgb(46, 204, 113));
public static Brush PETER_RIVER = new SolidColorBrush(Color.FromRgb(52, 152, 219));
public static Brush BELIZE_HOLE = new SolidColorBrush(Color.FromRgb(41, 128, 185));
public static Brush MIDNIGHT_BLUE = new SolidColorBrush(Color.FromRgb(44, 62, 80));
public static Brush CLOUDS = new SolidColorBrush(Color.FromRgb(236, 240, 241));
}
}
注意:颜色是来自Flat UI Color系列的网站,且颜色定义的类型的Brush,而不是Color。下面再给出FlatButton的Type定义,FlatButtonType.cs示例代码如下:
namespace Yd.WpfControls
{
public enum FlatButtonType
{
Default,
Warn,
Danger
}
}
第二步,创建一个自定义控件,他会自动创建一个样式Generic.xaml,这个是默认的控件样式定义的文件。创建的界面如下:
修改文件名为FlatButton,并继承自Button控件,FlatButton.cs示例代码如下:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Yd.WpfControls
{
public class FlatButton : Button
{
static FlatButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatButton),
new FrameworkPropertyMetadata(typeof(FlatButton)));
}
//自定义控件属性ButtonType,其DependencyProperty为ButtonType+Property
public static readonly DependencyProperty ButtonTypeProperty =
DependencyProperty.Register("ButtonType", typeof(FlatButtonType), typeof(FlatButton),
new PropertyMetadata(FlatButtonType.Default));
public FlatButtonType ButtonType
{
get { return (FlatButtonType)GetValue(ButtonTypeProperty); }
set { SetValue(ButtonTypeProperty, value); }
}
public static readonly DependencyProperty MouseOverBackgroundProperty =
DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(FlatButton),
new PropertyMetadata(Brushes.RoyalBlue));
public Brush MouseOverBackground
{
get { return (Brush)GetValue(MouseOverBackgroundProperty); }
set { SetValue(MouseOverBackgroundProperty, value); }
}
public static readonly DependencyProperty MouseOverForegroundProperty =
DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(FlatButton),
new PropertyMetadata(Brushes.White));
public Brush MouseOverForeground
{
get { return (Brush)GetValue(MouseOverForegroundProperty); }
set { SetValue(MouseOverForegroundProperty, value); }
}
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(FlatButton),
new PropertyMetadata(new CornerRadius(2)));
public CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
}
}
FlatButton的UI定义基本都是靠样式定义文件FlatButton.xaml,其类似于CSS,但是语法描述不同。FlatButton.xaml位于Style目录下,其示例代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Yd.WpfControls">
<Style TargetType="{x:Type local:FlatButton}">
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"/>
<Setter Property="FontFamily" Value="{x:Static local:FlatFonts.contentFontFamily}"/>
<Style.Triggers>
<Trigger Property="ButtonType" Value="Default">
<Setter Property="Background" Value="{x:Static local:FlatColors.PETER_RIVER}"/>
<Setter Property="Foreground" Value="{x:Static local:FlatColors.CLOUDS}"/>
<Setter Property="MouseOverBackground" Value="{x:Static local:FlatColors.BELIZE_HOLE}"/>
<Setter Property="MouseOverForeground" Value="{x:Static local:FlatColors.CLOUDS}"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FlatButton}">
<Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
<TextBlock x:Name="text" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="text" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Warn">
<Setter Property="Background" Value="#f1c40f"/>
<Setter Property="MouseOverBackground" Value="#f39c12"/>
<Setter Property="Foreground" Value="{x:Static local:FlatColors.CLOUDS}"/>
<Setter Property="MouseOverForeground" Value="#ecf0f1"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FlatButton}">
<Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
<TextBlock x:Name="text" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="text" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Danger">
<Setter Property="Background" Value="#c0392b"/>
<Setter Property="MouseOverBackground" Value="#e74c3c"/>
<Setter Property="Foreground" Value="{x:Static local:FlatColors.CLOUDS}"/>
<Setter Property="MouseOverForeground" Value="#ecf0f1"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FlatButton}">
<Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
<TextBlock x:Name="text" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="text" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
此样式定义中,首先需要明确样式是针对哪个控件的,其用如下命令指定:
<Style TargetType="{x:Type local:FlatButton}">
而local这个命名空间是在 xmlns:local="clr-namespace:Yd.WpfControls" 进行定义的,这个需要手动添加,否则内部找不到FlatButton空间。在样式表中,可以对属性进行绑定,其中的属性可以是自定义的属性,比如:
<Trigger Property="ButtonType" Value="Default">
也可以绑定到静态类对象中,比如前面定义的颜色笔刷和字体对象,如:
<Setter Property="Background" Value="{x:Static local:FlatColors.PETER_RIVER}"/>
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"/>
<Setter Property="FontFamily" Value="{x:Static local:FlatFonts.contentFontFamily}"/>
第三步,将样式FlatButton.xaml添加到默认的Generic.xaml中,否则则UI无法加载样式定义信息,Generic.xaml其代码如下:
<ResourceDictionary
xmlns="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>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatButton.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
注意:ResourceDictionary Source的定义中,/Yd.WpfControls;component/+样式表路径,这个前缀不可少。
第四步,编译后,可以将自定义控件添加到UI界面上,如下所示:
选中某个FlatButton控件,可以在属性窗口中进行属性设置,其中也包含自定义的属性,示例如下:
主界面窗口的示例代码如下:
<Window
xmlns="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:FlatButton Content="确定" HorizontalAlignment="Left" Height="37" Margin="89,83,0,0" VerticalAlignment="Top" ButtonType="Default" CornerRadius="18" Width="120" FontFamily="Microsoft YaHei" FontSize="16"/>
<WpfControls:FlatButton Content="取消" 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:FlatButton Content="删除" 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:FlatButton Content="FlatButton" HorizontalAlignment="Left" Margin="72,0,0,0" VerticalAlignment="Center" Height="37" Width="137"/>
</Grid>
</Window>
第五步,编译运行,主界面如下:
- 点赞
- 收藏
- 关注作者
评论(0)