WPF自定義控件與樣式-自定義按鈕(Button)


一、前言

程序界面上的按鈕多種多樣,常用的就這幾種:普通按鈕、圖標按鈕、文字按鈕、圖片文字混合按鈕。本文章記錄了不同樣式類型的按鈕實現方法。

二、固定樣式的按鈕

固定樣式的按鈕一般在臨時使用時或程序的樣式比較固定時才會使用,按鈕整體樣式不需要做大的改動。

2.1 普通按鈕-扁平化風格

先看效果:

定義Button的樣式,詳見代碼:

<Style x:Key="BtnInfoStyle" TargetType="Button">
            <Setter Property="Width" Value="70"/>
            <Setter Property="Height" Value="25"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Background" Value="#43a9c7"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
                            <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="border" Property="Background" Value="#2f96b4"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="border" Property="Background" Value="#2a89a4"/>
                            </Trigger>
                       </ControlTemplate.Triggers>
                 </ControlTemplate>
            </Setter.Value>
     </Setter>
</Style>

引用方法:

<Grid Background="White">
        <StackPanel Orientation="Horizontal" Margin="10" VerticalAlignment="Top">
            <Button Style="{StaticResource BtnInfoStyle}" Content="信息" Margin="5 0"/>
</Grid>

上述代碼實現了Button按鈕的扁平化樣式,如果你想調整顏色風格,通過修改Background的值可實現默認顏色,鼠標經過顏色以及鼠標按下顏色。

 2.2 圖標按鈕

先看效果:

Button樣式的代碼和扁平化Button差不多,只是把TextBlock控件替換成了Image控件,另外需要設置Button默認的背景色為透明。廢話不多說看代碼:

  <Style x:Key="BtnImageStyle1" TargetType="Button">
         <Setter Property="Cursor" Value="Hand"/>
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="Button">
                      <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                            <Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="/Images/button1.png" Stretch="None"/>
                      </Border>
                      <ControlTemplate.Triggers>
                         <Trigger Property="IsMouseOver" Value="True">
                             <Setter TargetName="Img" Property="Source" Value="/Images/button1.png"/>
                         </Trigger>
                         <Trigger Property="IsPressed" Value="True">
                             <Setter TargetName="Img" Property="Source" Value="/Images/button1.png"/>
                         </Trigger>
                      </ControlTemplate.Triggers>
                 </ControlTemplate>
            </Setter.Value>
       </Setter>
 </Style>

這里的button1.png需要自己准備圖片資源,IsMouseOver和IsPressed的圖片資源可自己替換,替換之后能有更豐富的效果呈現。

2.3 圖標文字混合按鈕

效果:

 

實現代碼:

 <Style x:Key="BtnImgTxtStyle1" TargetType="Button">
       <Setter Property="Foreground" Value="#555"/>
       <Setter Property="Template">
             <Setter.Value>
                  <ControlTemplate TargetType="Button">
                       <Border>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                <Image Source="Images/adshut.png" Stretch="None"/>
                                <TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            </StackPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Foreground" Value="#333333" TargetName="Txt"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                 </ControlTemplate>
            </Setter.Value>
       </Setter>
 </Style>

2.4 文字按鈕和2.3中的圖標文字按鈕樣式差不多,只需要把Image控件去掉就行。

三、復用性高的按鈕

  • 要想實現復用性高的按鈕,就必須新建自定義控件。下面這個實例通過自定義控件實現上述所有效果,並且可以隨意更改風格。
  • 首先在項目中右鍵-添加-新建項-自定義控件。

新建自定義控件之后,添加依賴屬性。代碼如下:

 public class ButtonEx : Button
    {
        static ButtonEx()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonEx), new FrameworkPropertyMetadata(typeof(ButtonEx)));
        }


        public ButtonType ButtonType
        {
            get { return (ButtonType)GetValue(ButtonTypeProperty); }
            set { SetValue(ButtonTypeProperty, value); }
        }

        public static readonly DependencyProperty ButtonTypeProperty =
            DependencyProperty.Register("ButtonType", typeof(ButtonType), typeof(ButtonEx), new PropertyMetadata(ButtonType.Normal));


        public ImageSource Icon
        {
            get { return (ImageSource)GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }

        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(ImageSource), typeof(ButtonEx), new PropertyMetadata(null));


        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(ButtonEx), new PropertyMetadata(new CornerRadius(0)));


        public Brush MouseOverForeground
        {
            get { return (Brush)GetValue(MouseOverForegroundProperty); }
            set { SetValue(MouseOverForegroundProperty, value); }
        }

        public static readonly DependencyProperty MouseOverForegroundProperty =
            DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());


        public Brush MousePressedForeground
        {
            get { return (Brush)GetValue(MousePressedForegroundProperty); }
            set { SetValue(MousePressedForegroundProperty, value); }
        }

        public static readonly DependencyProperty MousePressedForegroundProperty =
            DependencyProperty.Register("MousePressedForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());


        public Brush MouseOverBorderbrush
        {
            get { return (Brush)GetValue(MouseOverBorderbrushProperty); }
            set { SetValue(MouseOverBorderbrushProperty, value); }
        }

        public static readonly DependencyProperty MouseOverBorderbrushProperty =
            DependencyProperty.Register("MouseOverBorderbrush", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());


        public Brush MouseOverBackground
        {
            get { return (Brush)GetValue(MouseOverBackgroundProperty); }
            set { SetValue(MouseOverBackgroundProperty, value); }
        }

        public static readonly DependencyProperty MouseOverBackgroundProperty =
            DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());


        public Brush MousePressedBackground
        {
            get { return (Brush)GetValue(MousePressedBackgroundProperty); }
            set { SetValue(MousePressedBackgroundProperty, value); }
        }

        public static readonly DependencyProperty MousePressedBackgroundProperty =
            DependencyProperty.Register("MousePressedBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
    }

    public enum ButtonType
    {
        Normal,
        Icon,
        Text,
        IconText
    }

為不同類型按鈕設置樣式,代碼如下:

<Style TargetType="{x:Type local:ButtonEx}">
        <Style.Triggers>
            <Trigger Property="ButtonType" Value="Normal">
                <Setter Property="Background" Value="#43a9c7"/>
                <Setter Property="MouseOverBackground" Value="#2f96b4"/>
                <Setter Property="MousePressedBackground" Value="#2a89a4"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="MouseOverForeground" Value="White"/>
                <Setter Property="MousePressedForeground" Value="White"/>
                <Setter Property="BorderBrush" Value="Transparent"/>
                <Setter Property="BorderThickness" Value="0"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:ButtonEx}">
                            <Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
                                <TextBlock x:Name="txt" 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="txt" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
                                    <Setter TargetName="border" Property="BorderBrush" Value="{Binding MouseOverBorderbrush,RelativeSource={RelativeSource TemplatedParent}}"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter TargetName="border" Property="Background" Value="{Binding MousePressedBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
                                    <Setter TargetName="txt" Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
                                   
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ButtonType" Value="Icon">
                <Setter Property="Cursor" Value="Hand"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:ButtonEx}">
                            <Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                                <Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{TemplateBinding Icon}" Stretch="None"/>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Opacity" Value="0.8"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Opacity" Value="0.9"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ButtonType" Value="Text">
                <Setter Property="Cursor" Value="Hand"/>
                <Setter Property="Foreground" Value="#002c99"/>
                <Setter Property="MouseOverForeground" Value="#FF2c99"/>
                <Setter Property="MousePressedForeground" Value="#002c99"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:ButtonEx}">
                            <TextBlock x:Name="txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="ButtonType" Value="IconText">
                <Setter Property="Cursor" Value="Hand"/>
                <Setter Property="Foreground" Value="#555"/>
                <Setter Property="MouseOverForeground" Value="#555"/>
                <Setter Property="MousePressedForeground" Value="#555"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type local:ButtonEx}">
                            <Border>
                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                    <Image Source="{TemplateBinding Icon}" Stretch="None"/>
                                    <TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                </StackPanel>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
       
    </Style>

然后就可以引用該控件了:

 <Grid>
        <WrapPanel>
            <local:ButtonEx Content="信息" Width="75" Height="25" Margin="10" ButtonType="Normal"/>
            <local:ButtonEx Icon="/Images/button1.png"  Margin="10" ButtonType="Icon"/>
            <local:ButtonEx Content="文字按鈕" Margin="10" ButtonType="Text"/>
            <local:ButtonEx Content="圖文按鈕" Icon="/Images/adshut.png" Margin="10" ButtonType="IconText"/>
        </WrapPanel>
    </Grid>

效果如下:

 

至此已經完成Button控件的擴展功能,如果想要添加動畫或者設置圖標的位置和邊距等,可以自己另外添加依賴屬性來擴展。

 

所有代碼已經上傳到github:https://github.com/caomfan/WpfDemo.git

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM