WPF自定义控件05:ToggleButton
在不少的手机端应用程序中,经常可以看到一些开关按钮,它可以非常方便的进行状态的切换操作。本文将介绍一下自定义的开关按钮ToggleButton,它与FlatCheckBox实现过程非常类似,它也是继承自CheckBox。下面将详细介绍具体的实现细节。
1 WPF项目结构
基于之前创建的WPF示例项目,在其中创建一些新的关于ToggleButton的项目文件。本质上,ToggleButton是继承CheckBox控件,利用CheckBox控件的自身的属性和方法,可以减少自己实现的难度和复杂度。另外,通过自定义Style实现的Flat UI效果的ToggleButton。具体的项目结构如下图所示:
其中的Fonts目录下存放各种图标字体文件,Style目录下存放各种控件的UI 样式定义文件,ToggleButton.xaml就是ToggleButton控件的样式定义文件。另外,需要将其注册到Generic.xaml文件中。
2 WPF ToggleButton实现
首先在Yd.WpfControls项目中添加一个类ToggleButton.cs,它继承自CheckBox控件,示例代码如下:
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 ToggleButton : CheckBox
{
static ToggleButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ToggleButton),
new FrameworkPropertyMetadata(typeof(ToggleButton)));
}
public static readonly DependencyProperty OffTextProperty =
DependencyProperty.Register("OffText", typeof(string), typeof(ToggleButton),
new PropertyMetadata("Off"));
public string OffText
{
get { return (string)GetValue(OffTextProperty); }
set { SetValue(OffTextProperty, value); }
}
public static readonly DependencyProperty OnTextProperty =
DependencyProperty.Register("OnText", typeof(string), typeof(ToggleButton),
new PropertyMetadata("On"));
public string OnText
{
get { return (string)GetValue(OnTextProperty); }
set { SetValue(OnTextProperty, value); }
}
public static readonly DependencyProperty OnForegroundProperty =
DependencyProperty.Register("OnForeground", typeof(Brush), typeof(ToggleButton),
new PropertyMetadata(Brushes.Silver));
public Brush OnForeground
{
get { return (Brush)GetValue(OnForegroundProperty); }
set { SetValue(OnForegroundProperty, value); }
}
public static readonly DependencyProperty OnBackgroundProperty =
DependencyProperty.Register("OnBackground", typeof(Brush), typeof(ToggleButton),
new PropertyMetadata(Brushes.Green));
public Brush OnBackground
{
get { return (Brush)GetValue(OnBackgroundProperty); }
set { SetValue(OnBackgroundProperty, value); }
}
}
}
其中定义了几个属性,特别是OnText和OffText,它们分别代表开关控件在打开状态的文本和关闭状态的文本。默认情况下,OnText文本是On,而OffText文本是Off。另外OnBackground是打开状态下的背景色,OnForeground是打开状态下的字体颜色。ToggleButton控件的UI样式主要就是依靠ToggleButton.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.MergedDictionaries>
<Style TargetType="{x:Type local:ToggleButton}">
<Setter Property="Background" Value="{x:Static local:FlatColors.PETER_RIVER}"></Setter>
<Setter Property="Foreground" Value="#DDE8E1"></Setter>
<Setter Property="OnForeground" Value="{x:Static local:FlatColors.EMERALD}"></Setter>
<Setter Property="OnBackground" Value="{x:Static local:FlatColors.BELIZE_HOLE}"></Setter>
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"/>
<Setter Property="FontFamily" Value="{x:Static local:FlatFonts.contentFontFamily}"/>
<Setter Property="Cursor" Value="Hand"></Setter>
<Setter Property="Width" Value="75"></Setter>
<Setter Property="Height" Value="28"></Setter>
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="HorizontalAlignment" Value="Center"></Setter>
<Setter Property="Template">
<Setter.Value>
<!--控件模板-->
<ControlTemplate TargetType="{x:Type local:ToggleButton}">
<Grid x:Name="grid" VerticalAlignment="Center" >
<Border x:Name="border" Width="75" Height="28"
Background="{TemplateBinding Background}" SnapsToDevicePixels="True"
Margin="0,0,0,0" CornerRadius="14" Cursor="Hand">
<StackPanel Orientation="Horizontal">
<!--圆形-->
<Border x:Name="state" Width="24" Height="24" Margin="3,2,1,2" CornerRadius="12" SnapsToDevicePixels="True"
Background="{TemplateBinding Foreground}">
<Border.RenderTransform>
<TranslateTransform x:Name="transState" X="0"></TranslateTransform>
</Border.RenderTransform>
</Border>
<!--文本-->
<TextBlock Width="40" Foreground="{TemplateBinding Foreground}" x:Name="text"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
Text="{TemplateBinding OffText}" VerticalAlignment="Center"
TextAlignment="Center" Cursor="Hand">
<TextBlock.RenderTransform>
<TranslateTransform x:Name="transText" X="0"></TranslateTransform>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Border>
</Grid>
<!--触发器,切换有动画-->
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnText}" TargetName="text"/>
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnForeground}" TargetName="state"/>
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnForeground}" TargetName="text"/>
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnBackground}" TargetName="border"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="transState" Storyboard.TargetProperty="X" To="46" Duration="0:0:0.3" />
<DoubleAnimation Storyboard.TargetName="transText" Storyboard.TargetProperty="X" To="-25" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="transState" Storyboard.TargetProperty="X" To="0" Duration="0:0:0.3" />
<DoubleAnimation Storyboard.TargetName="transText" Storyboard.TargetProperty="X" To="0" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.5" TargetName="border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
通过触发器Trigger来确定ToggleButton属性IsChecked变化时,如何在UI上进行显示,比如是打开状态,属性IsChecked的值为true时,则会触发如下触发器定义的规则,其中关于transState控件元素沿着X轴往右边移动46,而文本transText则沿着X轴往左边移动25。
3 WPF ToggleButton测试
首先,需要重新生成一下项目文件,然后在WpfControls项目中添加自定义控件ToggleButton,MainWindow.xaml部分示例代码如下:
<WpfControls:ToggleButton Content="SwitchCheckBox" HorizontalAlignment="Left"
Margin="120,167,0,0" VerticalAlignment="Top"/>
<WpfControls:ToggleButton Content="SwitchCheckBox" OnText="开" OffText="关"
HorizontalAlignment="Left" Margin="286,167,0,0"
VerticalAlignment="Top"/>
运行界面如下:
- 点赞
- 收藏
- 关注作者
评论(0)