在不少的手机端应用程序中,经常可以看到一些开关按钮,它可以非常方便的进行状态的切换操作。本文将介绍一下自定义的开关按钮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控件,示例代码如下:
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Media; namespaceYd.WpfControls{ publicclassToggleButton : CheckBox { staticToggleButton() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ToggleButton), newFrameworkPropertyMetadata(typeof(ToggleButton))); } publicstaticreadonlyDependencyPropertyOffTextProperty=DependencyProperty.Register("OffText", typeof(string), typeof(ToggleButton), newPropertyMetadata("Off")); publicstringOffText { get { return (string)GetValue(OffTextProperty); } set { SetValue(OffTextProperty, value); } } publicstaticreadonlyDependencyPropertyOnTextProperty=DependencyProperty.Register("OnText", typeof(string), typeof(ToggleButton), newPropertyMetadata("On")); publicstringOnText { get { return (string)GetValue(OnTextProperty); } set { SetValue(OnTextProperty, value); } } publicstaticreadonlyDependencyPropertyOnForegroundProperty=DependencyProperty.Register("OnForeground", typeof(Brush), typeof(ToggleButton), newPropertyMetadata(Brushes.Silver)); publicBrushOnForeground { get { return (Brush)GetValue(OnForegroundProperty); } set { SetValue(OnForegroundProperty, value); } } publicstaticreadonlyDependencyPropertyOnBackgroundProperty=DependencyProperty.Register("OnBackground", typeof(Brush), typeof(ToggleButton), newPropertyMetadata(Brushes.Green)); publicBrushOnBackground { get { return (Brush)GetValue(OnBackgroundProperty); } set { SetValue(OnBackgroundProperty, value); } } } }
其中定义了几个属性,特别是OnText和OffText,它们分别代表开关控件在打开状态的文本和关闭状态的文本。默认情况下,OnText文本是On,而OffText文本是Off。另外OnBackground是打开状态下的背景色,OnForeground是打开状态下的字体颜色。ToggleButton控件的UI样式主要就是依靠ToggleButton.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/IconFont.xaml"/></ResourceDictionary.MergedDictionaries><StyleTargetType="{x:Type local:ToggleButton}"><SetterProperty="Background"Value="{x:Static local:FlatColors.PETER_RIVER}"></Setter><SetterProperty="Foreground"Value="#DDE8E1"></Setter><SetterProperty="OnForeground"Value="{x:Static local:FlatColors.EMERALD}"></Setter><SetterProperty="OnBackground"Value="{x:Static local:FlatColors.BELIZE_HOLE}"></Setter><SetterProperty="FontSize"Value="{x:Static local:FlatFonts.contentFontSize}"/><SetterProperty="FontFamily"Value="{x:Static local:FlatFonts.contentFontFamily}"/><SetterProperty="Cursor"Value="Hand"></Setter><SetterProperty="Width"Value="75"></Setter><SetterProperty="Height"Value="28"></Setter><SetterProperty="VerticalAlignment"Value="Center"></Setter><SetterProperty="HorizontalAlignment"Value="Center"></Setter><SetterProperty="Template"><Setter.Value><!--控件模板--><ControlTemplateTargetType="{x:Type local:ToggleButton}"><Gridx:Name="grid"VerticalAlignment="Center"><Borderx:Name="border"Width="75"Height="28"Background="{TemplateBinding Background}"SnapsToDevicePixels="True"Margin="0,0,0,0"CornerRadius="14"Cursor="Hand"><StackPanelOrientation="Horizontal"><!--圆形--><Borderx:Name="state"Width="24"Height="24"Margin="3,2,1,2"CornerRadius="12"SnapsToDevicePixels="True"Background="{TemplateBinding Foreground}"><Border.RenderTransform><TranslateTransformx:Name="transState"X="0"></TranslateTransform></Border.RenderTransform></Border><!--文本--><TextBlockWidth="40"Foreground="{TemplateBinding Foreground}"x:Name="text"FontFamily="{TemplateBinding FontFamily}"FontSize="{TemplateBinding FontSize}"Text="{TemplateBinding OffText}"VerticalAlignment="Center"TextAlignment="Center"Cursor="Hand"><TextBlock.RenderTransform><TranslateTransformx:Name="transText"X="0"></TranslateTransform></TextBlock.RenderTransform></TextBlock></StackPanel></Border></Grid><!--触发器,切换有动画--><ControlTemplate.Triggers><TriggerProperty="IsChecked"Value="True"><SetterProperty="Text"Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnText}"TargetName="text"/><SetterProperty="Background"Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnForeground}"TargetName="state"/><SetterProperty="Foreground"Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnForeground}"TargetName="text"/><SetterProperty="Background"Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=OnBackground}"TargetName="border"/><Trigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimationStoryboard.TargetName="transState"Storyboard.TargetProperty="X"To="46"Duration="0:0:0.3"/><DoubleAnimationStoryboard.TargetName="transText"Storyboard.TargetProperty="X"To="-25"Duration="0:0:0.3"/></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimationStoryboard.TargetName="transState"Storyboard.TargetProperty="X"To="0"Duration="0:0:0.3"/><DoubleAnimationStoryboard.TargetName="transText"Storyboard.TargetProperty="X"To="0"Duration="0:0:0.3"/></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger><TriggerProperty="IsEnabled"Value="false"><SetterProperty="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:ToggleButtonContent="SwitchCheckBox"HorizontalAlignment="Left"Margin="120,167,0,0"VerticalAlignment="Top"/><WpfControls:ToggleButtonContent="SwitchCheckBox"OnText="开"OffText="关"HorizontalAlignment="Left"Margin="286,167,0,0"VerticalAlignment="Top"/>
运行界面如下: