15、wpf之button样式小记

前言:Button算是开发中用到的比较多的控件了,最开始使用原生的样式,长方形的样子,然后设置下Button的Content属性。随着学习的深入,需要去设置下Button的背景色,再往后就需要改下Button的模板来满足更高的需求设计。

一、简介

可以看到,Button继承至ContentControl控件, Button有个Content属性而这个Content可以是多种控件形式,查看Button的模板可以看到,用来承载这个内容的是一个ContentPresenter控件。

通过官网可以看到这个ContentPresenter类的继承关系 

二、Background

简单的如下

<Button Background="AliceBlue"/>

可以看到,这个Background属性类型是Brush,因此我们可以通过应用不同的Brush来改变Button的Background,从而使Background更加丰富。

官网中对Brush的注解,Brush有多个继承者,都可以用

2.1  LinearGradientBrush

<Button Width="60" Height="60">
    <Button.Background>
        <LinearGradientBrush EndPoint="0.851,0.838" StartPoint="0.115,0.169">
            <GradientStop Color="#FFA21212" Offset="0"/>
            <GradientStop Color="#FFF8C906" Offset="1"/>
        </LinearGradientBrush>
    </Button.Background>
</Button>

2.2 RadialGradientBrush

<Button Width="60" Height="60">
    <Button.Background>
        <RadialGradientBrush>
            <GradientStop Color="#FFA21212" Offset="1"/>
            <GradientStop Color="#FFF8C906" Offset="0"/>
        </RadialGradientBrush>
    </Button.Background>
</Button>

2.3 ImageBrush 

            <Button Width="60" Height="60">
                <Button.Background>
                    <ImageBrush ImageSource="/项目.png"/>
                </Button.Background>
            </Button>

2.4 DrawingBrush 

            <Button Width="60" Height="60">
                <Button.Background>
                    <DrawingBrush Viewport="0,0,0.5,0.5" TileMode="Tile">
                        <DrawingBrush.Drawing>
                            <GeometryDrawing Brush="Red">
                                <GeometryDrawing.Geometry>
                                    <GeometryGroup>
                                        <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" />
                                        <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" />
                                    </GeometryGroup>
                                </GeometryDrawing.Geometry>
                                <GeometryDrawing.Pen>
                                    <Pen Thickness="10">
                                        <Pen.Brush>
                                            <LinearGradientBrush>
                                                <GradientStop Offset="0.0" Color="Black" />
                                                <GradientStop Offset="1.0" Color="Gray" />
                                            </LinearGradientBrush>
                                        </Pen.Brush>
                                    </Pen>
                                </GeometryDrawing.Pen>
                            </GeometryDrawing>
                        </DrawingBrush.Drawing>
                    </DrawingBrush>
                </Button.Background>
            </Button>

2.5 VisualBrush

            <Button Width="60" Height="60">
                <Button.Background>
                    <VisualBrush>
                        <VisualBrush.Visual>
                            <StackPanel Background="White">
                                <Rectangle Width="25" Height="25" Fill="Orange" Margin="6" />
                                <TextBlock FontSize="10pt" Margin="2">BrawDraw</TextBlock>
                                <Button Margin="10">Button</Button>
                            </StackPanel>
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Button.Background>
            </Button>

二、Content

2.1 字符串

<!--Create a Button with a string as its content.-->
<Button Content="1111111111" Height="60" Width="60"/>
<Button>This is string content of a Button</Button>

2.2  DateTime object

<!--Create a Button with a DateTime object as its content.-->
<Button xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <sys:DateTime>2004/3/4 13:6:55</sys:DateTime>
</Button>

2.3 UIElement

<!--Create a Button with a single UIElement as its content.-->
<Button>
  <Rectangle Height="40" Width="40" Fill="Blue"/>
</Button>

2.4 panel

<!--Create a Button with a panel that contains multiple objects 
as its content.-->
<Button>
  <StackPanel>
    <Ellipse Height="40" Width="40" Fill="Blue"/>
    <TextBlock TextAlignment="Center">Button</TextBlock>
  </StackPanel>
</Button>

2.5 说明

Because the Content property is of type Object, there are no restrictions on what you can put in a ContentControl. The Content is displayed by a ContentPresenter, which is in the ControlTemplate of the ContentControl. Every ContentControl type in WPF has a ContentPresenter in its default ControlTemplate

由于Content属性的类型是Object,因此对可以放入的内容ContentControl没有限制。该Content属性通过ContentPresenter显示,而这个ContentPresenter存在于ContentControl的ControlTemplate属性中。WPF中的每一个ContentControl类型控件都有一个ContentPresenter属性,默认存在ControlTemplate中。

三、外观

The ContentPresenter uses the following logic to display the Content (ContentPresenter就是用来显示Content的,下面是显示逻辑):

3.1 原生样式

        <Style x:Key="ButtonStyle2" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual1}"/>
            <Setter Property="Background" Value="{StaticResource Button.Static.Background1}"/>
            <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border1}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                            <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsDefaulted" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background1}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border1}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background1}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border1}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background1}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border1}"/>
                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground1}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

有关外观的设计就在ControlTemplate属性上,这个原生的没做什么改变,如果设置Content为string,就会像上面最后一条一样,Content调用ToString去转换并创建个TextBlock去承载这个转换后的string。

3.2 UIElement

使用image作为Content的元素,上面第四条所说的。

<Button Height="60" Width="60">
    <Image Source="/项目.png"/>
</Button>

3.2 修改ControlTemplate

原生的样式,边框很明显,这时就需要修改下ControlTemplate了

<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
            <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
            <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Padding" Value="1"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="0"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Image Source="/Resource/send.png" Margin="0 10 0 0"/>
                            <Border x:Name="border"  BorderThickness="1" SnapsToDevicePixels="true" Grid.Row="1">
                                <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsDefaulted" Value="true">
                                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
                                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 我们把ControlTemplate摘出来看看,原样式中使用一个Border包裹一个ContentPrensenter。

修改后使用了Grid作为ContentPresenter的父容器。其实这里分了两层,一层高度是0,其实就一层。

这里还有个问题,就是鼠标移动上去后,会有个背景,不好看

这个背景是在 ControlTemplate.Triggers中设置的,设置的属性是IsMouseOver。想去掉这个背景,暴力点的做法直接注释掉那段代码。

3.3 升级

鼠标移上去会放大这个Content,笔者代码中Content设置为Image类型的。

        <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate  TargetType="{x:Type Button}">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="Storyboard1">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="grid">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1.25"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="grid">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1.25"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Key="Storyboard2">
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="grid">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="grid">
                                    <SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>
                        <Grid x:Name="grid" RenderTransformOrigin="0.5,0.5">
                            <Grid.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform/>
                                    <SkewTransform/>
                                    <RotateTransform/>
                                    <TranslateTransform/>
                                </TransformGroup>
                            </Grid.RenderTransform>
                            <Label Name="lbl" Content="{TemplateBinding Content}" Background="Transparent" Height="{TemplateBinding Height}"
                           Width="{TemplateBinding Width}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsFocused" Value="True"/>
                            <Trigger Property="IsDefaulted" Value="True"/>
                            <Trigger Property="IsMouseOver" Value="True">
                                <!--<Setter Property="Background" TargetName="lbl" Value="red"/>-->
                                <Trigger.ExitActions>
                                    <BeginStoryboard x:Name="Storyboard_Copy1_BeginStoryboard" Storyboard="{StaticResource Storyboard2}"/>
                                </Trigger.ExitActions>
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                                </Trigger.EnterActions>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter Property="Background" TargetName="lbl" Value="#000000FF"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False"/>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

加了个动画,然后在 IsMouseOver事件中进行操作。

四、引用文献

4.1 Button 类 (System.Windows.Controls) | Microsoft Docs

4.2 ContentPresenter 类 (System.Windows.Controls) | Microsoft Docs

4.3 Brush 类 (System.Windows.Media) | Microsoft Docs

4.4 简述WPF中的画刷(Brush)_Andrewniu的博客-CSDN博客_brush wpf

4.5 ContentControl.Content 属性 (System.Windows.Controls) | Microsoft Docs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值