WPF自定义控件07:FlatTextBox
在不少的应用程序中,作为基本输入的文本框(TextBox)是少不了的,它可以很方便获取用户输入的值。本文将介绍一下自定义的文本框控件FlatTextBox,它与FlatCheckBox实现过程非常类似,它是继承自TextBox,但使用自定义的UI样式来美化界面,并添加了特有的一些依赖属性。下面将详细介绍具体的实现细节。
1 WPF项目结构
基于之前创建的WPF示例项目,在其中创建一个新的关于FlatTextBox的项目文件。本质上,FlatTextBox是继承TextBox控件,利用TextBox控件自身的属性和方法,可以减少FlatTextBox实现的难度和复杂度。首先,给出本项目文件结构,如下图所示:
其中的Fonts目录下存放各种图标字体文件,Style目录下存放各种控件的UI 样式定义文件,FlatComboBox.xaml就是FlatComboBox控件的样式定义文件。另外,需要将其注册到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/IconFont.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatCheckBox.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatRadioButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/ToggleButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatComboBox.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatTextBox.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
2 WPF FlatTextBox实现
首先在Yd.WpfControls项目中添加一个类FlatTextBox.cs,它继承自TextBox控件,示例代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Yd.WpfControls
{
public class FlatTextBox : TextBox
{
static FlatTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatTextBox),
new FrameworkPropertyMetadata(typeof(FlatTextBox)));
}
public static readonly DependencyProperty TextTypeProperty =
DependencyProperty.Register("TextType", typeof(FlatButtonType), typeof(FlatTextBox),
new PropertyMetadata(FlatButtonType.Default));
public FlatButtonType TextType
{
get { return (FlatButtonType)GetValue(TextTypeProperty); }
set { SetValue(TextTypeProperty, value); }
}
public static readonly DependencyProperty IsRequreProperty =
DependencyProperty.Register("IsRequre", typeof(bool), typeof(FlatTextBox),
new PropertyMetadata(false));
public bool IsRequre
{
get { return (bool)GetValue(IsRequreProperty); }
set { SetValue(IsRequreProperty, value); }
}
public bool IsValidate()
{
if ( IsRequre)
{
if (!string.IsNullOrEmpty(this.Text))
{
TextType = FlatButtonType.Default;
return true;
}
else
{
TextType = FlatButtonType.Danger;
return true;
}
}
else
{
TextType = FlatButtonType.Default;
return true;
}
}
}
}
其中扩展了2个依赖属性,即TextType属性和IsRequre属性,前者代表当前输入框的类型,是Default状态的,还是Warn状态的,还是Danger状态;而后者代表当前文本框是否为必输,如果值是true,则当文本框值为空的时候,会显示红色边框。当然这个验证过程通过自定义的IsValidate()方法实现。
FlatTextBox控件的UI样式主要就是依靠FlatTextBox.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">
<Style TargetType="{x:Type local:FlatTextBox}">
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"/>
<Setter Property="FontFamily" Value="{x:Static local:FlatFonts.contentFontFamily}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Height" Value="28"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Style.Triggers>
<Trigger Property="TextType" Value="Default">
<Setter Property="Foreground" Value="{x:Static local:FlatColors.SILVER}"/>
<Setter Property="BorderBrush" Value="{x:Static local:FlatColors.SILVER}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True"
CornerRadius="14" Padding="10 0">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.ASBESTOS}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.ASBESTOS}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="TextType" Value="Warn">
<Setter Property="Foreground" Value="{x:Static local:FlatColors.SUN_FLOWER}"/>
<Setter Property="BorderBrush" Value="{x:Static local:FlatColors.SUN_FLOWER}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True"
CornerRadius="14" Padding="10 0">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.ORANGE}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.ORANGE}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="TextType" Value="Danger">
<Setter Property="Foreground" Value="{x:Static local:FlatColors.ALIZARIN}"/>
<Setter Property="BorderBrush" Value="{x:Static local:FlatColors.ALIZARIN}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True"
CornerRadius="14" Padding="10 0">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.POMEGRANATE}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{x:Static local:FlatColors.POMEGRANATE}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
其中的文本框默认的字体和字体大小通过如下设置方法实现:
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"/>
<Setter Property="FontFamily" Value="{x:Static local:FlatFonts.contentFontFamily}"/>
另外就是,定义了根据依赖属性TextType的值,通过触发器来设置不同的属性,从而得到不同UI样式的目的。
3 WPF FlatTextBox测试
首先,需要重新生成一下项目文件,然后在WpfControls项目中添加自定义控件FlatTextBox,Window5.xaml部分示例代码如下:
<Window x:Class="WpfControls.Window5"
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"
xmlns:local="clr-namespace:WpfControls"
mc:Ignorable="d"
Title="Window5" Height="350" Width="500">
<Grid>
<WpfControls:FlatTextBox HorizontalAlignment="Center" Margin="0,81,0,0"
Text="FlatTextBox" TextWrapping="Wrap"
VerticalAlignment="Top" Width="320"
Name="flattextbox1" IsRequre="True"/>
<WpfControls:FlatTextBox HorizontalAlignment="Center" Margin="0,135,0,0"
Text="FlatTextBox" TextWrapping="Wrap"
VerticalAlignment="Top" Width="320"
TextType="Warn"/>
<WpfControls:FlatTextBox HorizontalAlignment="Center" Margin="0,184,0,0"
Text="FlatTextBox" TextWrapping="Wrap"
VerticalAlignment="Top" Width="320"
TextType="Danger"/>
</Grid>
</Window>
其中的Name="flattextbox1"给控件起一个名称,这样可以在后台用C#来进行访问,下面给出后台示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WpfControls
{
/// <summary>
/// Window5.xaml 的交互逻辑
/// </summary>
public partial class Window5 : Window
{
public Window5()
{
InitializeComponent();
this.flattextbox1.Text = "";
this.flattextbox1.IsValidate();
}
}
}
运行界面如下:
- 点赞
- 收藏
- 关注作者
评论(0)