zoukankan      html  css  js  c++  java
  • WPF自定义控件与样式(2)-自定义按钮FButton

    一.前言.效果图

      申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。 

    还是先看看效果图吧:

       

      

       定义Button按钮名称叫FButton,主要是集成了字体图标(参考上一篇:WPF自定义控件与样式1-矢量字体图标(iconfont))。其实在WPF里,要实现本文FButton的需求,完全可以不用自定义控件,使用样式、模板就可以搞定了的。

    二.按钮FButton控件定义

    2.1 FButton继承自微软基础控件Button (C#代码)

      FButton继承自微软基础控件Button,没有什么逻辑代码,主要扩展了几个属性:

    • 控件外观控制的属性,如圆角、鼠标悬浮前景色背景色、是否开启动画(鼠标悬停时小图标转一圈,移开又转回去)、鼠标按下颜色等;
    • 字体图标相关属性,如字符值、字体图标大小、字体图标间距等。

    详见代码:

        /// <summary>
        /// FButton.xaml 的交互逻辑
        /// </summary>
    
        public partial class FButton : Button
        {
            public static readonly DependencyProperty PressedBackgroundProperty =
                DependencyProperty.Register("PressedBackground", typeof(Brush), typeof(FButton), new PropertyMetadata(Brushes.DarkBlue));
            /// <summary>
            /// 鼠标按下背景样式
            /// </summary>
            public Brush PressedBackground
            {
                get { return (Brush)GetValue(PressedBackgroundProperty); }
                set { SetValue(PressedBackgroundProperty, value); }
            }
    
            public static readonly DependencyProperty PressedForegroundProperty =
                DependencyProperty.Register("PressedForeground", typeof(Brush), typeof(FButton), new PropertyMetadata(Brushes.White));
            /// <summary>
            /// 鼠标按下前景样式(图标、文字)
            /// </summary>
            public Brush PressedForeground
            {
                get { return (Brush)GetValue(PressedForegroundProperty); }
                set { SetValue(PressedForegroundProperty, value); }
            }
    
            public static readonly DependencyProperty MouseOverBackgroundProperty =
                DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(FButton), new PropertyMetadata(Brushes.RoyalBlue));
            /// <summary>
            /// 鼠标进入背景样式
            /// </summary>
            public Brush MouseOverBackground
            {
                get { return (Brush)GetValue(MouseOverBackgroundProperty); }
                set { SetValue(MouseOverBackgroundProperty, value); }
            }
    
            public static readonly DependencyProperty MouseOverForegroundProperty =
                DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(FButton), new PropertyMetadata(Brushes.White));
            /// <summary>
            /// 鼠标进入前景样式
            /// </summary>
            public Brush MouseOverForeground
            {
                get { return (Brush)GetValue(MouseOverForegroundProperty); }
                set { SetValue(MouseOverForegroundProperty, value); }
            }
    
            public static readonly DependencyProperty FIconProperty =
                DependencyProperty.Register("FIcon", typeof(string), typeof(FButton), new PropertyMetadata("ue604"));
            /// <summary>
            /// 按钮字体图标编码
            /// </summary>
            public string FIcon
            {
                get { return (string)GetValue(FIconProperty); }
                set { SetValue(FIconProperty, value); }
            }
    
            public static readonly DependencyProperty FIconSizeProperty =
                DependencyProperty.Register("FIconSize", typeof(int), typeof(FButton), new PropertyMetadata(20));
            /// <summary>
            /// 按钮字体图标大小
            /// </summary>
            public int FIconSize
            {
                get { return (int)GetValue(FIconSizeProperty); }
                set { SetValue(FIconSizeProperty, value); }
            }
    
            public static readonly DependencyProperty FIconMarginProperty = DependencyProperty.Register(
                "FIconMargin", typeof(Thickness), typeof(FButton), new PropertyMetadata(new Thickness(0, 1, 3, 1)));
            /// <summary>
            /// 字体图标间距
            /// </summary>
            public Thickness FIconMargin
            {
                get { return (Thickness)GetValue(FIconMarginProperty); }
                set { SetValue(FIconMarginProperty, value); }
            }
    
            public static readonly DependencyProperty AllowsAnimationProperty = DependencyProperty.Register(
                "AllowsAnimation", typeof(bool), typeof(FButton), new PropertyMetadata(true));
            /// <summary>
            /// 是否启用Ficon动画
            /// </summary>
            public bool AllowsAnimation
            {
                get { return (bool)GetValue(AllowsAnimationProperty); }
                set { SetValue(AllowsAnimationProperty, value); }
            }
    
            public static readonly DependencyProperty CornerRadiusProperty =
                DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(FButton), new PropertyMetadata(new CornerRadius(2)));
            /// <summary>
            /// 按钮圆角大小,左上,右上,右下,左下
            /// </summary>
            public CornerRadius CornerRadius
            {
                get { return (CornerRadius)GetValue(CornerRadiusProperty); }
                set { SetValue(CornerRadiusProperty, value); }
            }
    
            public static readonly DependencyProperty ContentDecorationsProperty = DependencyProperty.Register(
                "ContentDecorations", typeof(TextDecorationCollection), typeof(FButton), new PropertyMetadata(null));
            public TextDecorationCollection ContentDecorations
            {
                get { return (TextDecorationCollection)GetValue(ContentDecorationsProperty); }
                set { SetValue(ContentDecorationsProperty, value); }
            }
    
            static FButton()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(FButton), new FrameworkPropertyMetadata(typeof(FButton)));
            }
        }
    View Code

    2.2 FButton控件模板定义

      模板内容分为两部分,第一部分为为基本结构,第二部分就是触发器,用触发器实现按钮不同状态的样式控制,详见代码:

        <!--FButton模板-->
        <ControlTemplate x:Key="FButton_Template" TargetType="{x:Type local:FButton}">
            <Border x:Name="border" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Background}" 
                                        Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}" 
                                        CornerRadius="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=CornerRadius}" 
                                        Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}">
                <!--Icon/Text-->
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" 
                            Margin="{TemplateBinding Padding}"
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
                    <TextBlock x:Name="icon"  Margin="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FIconMargin}" 
                               RenderTransformOrigin="0.5,0.5" Style="{StaticResource FIcon}"
                               Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= FIcon}" 
                               FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= FIconSize}" 
                               Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Foreground}">
                        <TextBlock.RenderTransform>
                            <RotateTransform x:Name="transIcon" Angle="0"/>
                        </TextBlock.RenderTransform>
                    </TextBlock>
    
                    <TextBlock VerticalAlignment="Center"  x:Name="txt" 
                               TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}" 
                                                   Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" 
                                                   FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FontSize}" 
                                                   Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Foreground}"></TextBlock>
                </StackPanel>
            </Border>
            <!--触发器-->
            <ControlTemplate.Triggers>
                <!--设置鼠标进入时的背景、前景样式-->
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=MouseOverBackground}" TargetName="border" />
                    <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=MouseOverForeground}" TargetName="icon"/>
                    <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=MouseOverForeground}" TargetName="txt"/>
                </Trigger>
                <!--Ficon的动画触发器-->
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsMouseOver" Value="true"></Condition>
                        <Condition Property="AllowsAnimation" Value="true"></Condition>
                    </MultiTrigger.Conditions>
                    <MultiTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="transIcon" Storyboard.TargetProperty="Angle" To="180" Duration="0:0:0.2" />
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiTrigger.EnterActions>
                    <MultiTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="transIcon" Storyboard.TargetProperty="Angle" To="0" Duration="0:0:0.2" />
                            </Storyboard>
                        </BeginStoryboard>
                    </MultiTrigger.ExitActions>
                </MultiTrigger>
                <!--鼠标按下时的前景、背景样式-->
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=PressedBackground}" TargetName="border" />
                    <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=PressedForeground}" TargetName="icon"/>
                    <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                    Path=PressedForeground}" TargetName="txt"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Opacity" Value="0.5" TargetName="border"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    View Code

    2.3 FButton基本样式

      样式定义代码:  

        <!--默认样式-->
        <Style TargetType="{x:Type local:FButton}">
            <Setter Property="Background" Value="{StaticResource ButtonBackground}" />
            <Setter Property="Foreground" Value="{StaticResource ButtonForeground}" />
            <Setter Property="MouseOverBackground" Value="{StaticResource ButtonMouseOverBackground}" />
            <Setter Property="MouseOverForeground" Value="{StaticResource ButtonMouseOverForeground}" />
            <Setter Property="PressedBackground" Value="{StaticResource ButtonPressedBackground}" />
            <Setter Property="PressedForeground" Value="{StaticResource ButtonPressedForeground}" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="30" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="FIconSize" Value="22" />
            <Setter Property="Template" Value="{StaticResource FButton_Template}"/>
            <Setter Property="Padding" Value="3,1,3,1" />
            <Setter Property="Content" Value="{x:Null}" />
            <Setter Property="FIconMargin" Value="0,0,5,0" />
            <Setter Property="AllowsAnimation" Value="False" />
        </Style>

      基本按钮的效果,参考(一.前言-效果图),示例代码:

            <StackPanel >
                <core:FButton FIcon="&#xe602;" Margin="3">系统换转</core:FButton>
                <core:FButton FIcon="&#xe628;" Margin="3" Width="140" Height="40" Background="#771C79" MouseOverBackground="#F20BA0"  Click="FButton_Click" >WaitingBox</core:FButton>
                <core:FButton FIcon="&#xe629;" Margin="3" Width="140" Height="40" Background="#12B512" IsDefault="True" MouseOverBackground="#08EE08" Click="FButton_Click_WindowBase">WindowBase</core:FButton>
    
                <core:FButton FIcon="&#xe64f;" Margin="5,0,0,0" CornerRadius="16,0,0,16" AllowsAnimation="True" Click="FButton_Click_Info">Info</core:FButton>
                <core:FButton FIcon="&#xe628;" CornerRadius="0" Click="FButton_Click_Question">Question</core:FButton>
                <core:FButton FIcon="&#xe628;" CornerRadius="0" Click="FButton_Click_Warning">Warining</core:FButton>
                <core:FButton FIcon="&#xe629;" CornerRadius="0,16,16,0" AllowsAnimation="True" Click="FButton_Click_Error">Error</core:FButton>
            </StackPanel>

    2.4 FButton透明背景样式

       背景透明效果的按钮样式 

        <!--背景透明的FButton样式-->
        <Style x:Key="FButton_Transparency" TargetType="{x:Type local:FButton}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="MouseOverBackground" Value="Transparent" />
            <Setter Property="PressedBackground" Value="Transparent" />
            <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
            <Setter Property="MouseOverForeground" Value="{StaticResource MouseOverForeground}" />
            <Setter Property="PressedForeground" Value="{StaticResource PressedForeground}" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="Height" Value="Auto" />
            <Setter Property="Width" Value="Auto" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="FIconSize" Value="20" />
            <Setter Property="Template" Value="{StaticResource FButton_Template}"/>
            <Setter Property="Padding" Value="3,1,3,1" />
            <Setter Property="Content" Value="{x:Null}" />
            <Setter Property="FIconMargin" Value="0,0,2,0" />
            <Setter Property="AllowsAnimation" Value="False" />
            <Setter Property="Cursor" Value="Hand" />
        </Style>

      示例及效果:

                <core:FButton FIcon="&#xe627;" Margin="5" FIconMargin="0" FIconSize="30" Style="{StaticResource FButton_Transparency}" ></core:FButton>
                <core:FButton FIcon="&#xe628;" Margin="5" Style="{StaticResource FButton_Transparency}"></core:FButton>
                <core:FButton FIcon="&#xe629;" Margin="5" Style="{StaticResource FButton_Transparency}" IsEnabled="False"></core:FButton>
    
    
                <core:FButton FIcon="&#xe60e;" Margin="3" Style="{StaticResource FButton_Transparency}">如何开启调试模式?</core:FButton>
                <core:FButton FIcon="&#xe617;" Margin="3" Style="{StaticResource FButton_Transparency}" IsEnabled="False">设备检测</core:FButton>
                <core:FButton FIcon="&#xe629;" Margin="3" Style="{StaticResource FButton_Transparency}">爸爸回来了</core:FButton>

      

    2.3 类似LinkButton(超链接)样式

    样式定义:

        <!--LinkButton的FButton样式,默认无FIcon-->
        <Style x:Key="FButton_LinkButton" TargetType="{x:Type local:FButton}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="MouseOverBackground" Value="Transparent" />
            <Setter Property="PressedBackground" Value="Transparent" />
            <Setter Property="Foreground" Value="{StaticResource LinkForeground}" />
            <Setter Property="MouseOverForeground" Value="{StaticResource MouseOverForeground}" />
            <Setter Property="PressedForeground" Value="{StaticResource PressedForeground}" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="Height" Value="Auto" />
            <Setter Property="Width" Value="Auto" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="FontSize" Value="13" />
            <Setter Property="FIconSize" Value="20" />
            <Setter Property="Template" Value="{StaticResource FButton_Template}"/>
            <Setter Property="Padding" Value="3,1,3,1" />
            <Setter Property="Content" Value="{x:Null}" />
            <Setter Property="FIconMargin" Value="0" />
            <Setter Property="FIcon" Value="" />
            <Setter Property="AllowsAnimation" Value="False" />
            <Setter Property="ContentDecorations" Value="Underline" />
            <Setter Property="Cursor" Value="Hand" />
        </Style>

    示例及效果:

                <core:FButton Margin="3,15" Style="{StaticResource FButton_LinkButton}" >如何开启调试模式?</core:FButton>
                <core:FButton FIcon="&#xe617;" Margin="3" Style="{StaticResource FButton_LinkButton}">设备检测</core:FButton>
                <core:FButton Margin="3" Style="{StaticResource FButton_LinkButton}">爸爸回来了</core:FButton>

      

     附录:参考引用

    WPF自定义控件与样式(1)-矢量字体图标(iconfont)

    WPF自定义控件与样式(2)-自定义按钮FButton

    WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

    WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式

    WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

    WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu

    WPF自定义控件与样式(10)-进度控件ProcessBar自定义样 

    WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现

    WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表

    WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox

    WPF自定义控件与样式(14)-轻量MVVM模式实践 

    WPF自定义控件与样式(15)-终结篇

     

    版权所有,文章来源:http://www.cnblogs.com/anding

    个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。

  • 相关阅读:
    Silverlight中使用MVVM(2)-(提高)
    Silverlight中使用MVVM(1)--基础
    数据库设计 Step by Step (2)——数据库生命周期
    数据库设计 Step by Step (1)——扬帆启航
    心火肝火胃火肺火的症状区别及治疗方法
    ESP8266 wifi 模块配置,Wechat+APP控制实现
    PCB名詞解釋:通孔、盲孔、埋孔(转载)
    123
    电子称DIY(贴应变片+写代码)
    STM32常见问题
  • 原文地址:https://www.cnblogs.com/anding/p/4968050.html
Copyright © 2011-2022 走看看