wpf研究之道——自定义Button控件

      我们知道WPF中普通的按钮,长得丑,所以自定义按钮,在所难免。我们给按钮添加 MoveBrush,EnterBrush两把刷子,其实就是鼠标经过和鼠标按下的效果。只不过这不是普通的刷子,而是带图片的ImageBrush刷子。

     

 1  public class ShareButton : Button
 2     {
 3         /// <summary>
 4         /// 鼠标移走
 5         /// </summary>
 6         public static readonly DependencyProperty MoveBrushProperty;
 7         public Brush MoveBrush
 8         {
 9             set
10             {
11                 base.SetValue(ShareButton.MoveBrushProperty, value);
12             }
13             get
14             {
15                 return base.GetValue(ShareButton.MoveBrushProperty) as Brush;
16             }
17         }
18         public static readonly DependencyProperty EnterBrushProperty;
19         /// <summary>
20         /// 鼠标进入
21         /// </summary>
22         public Brush EnterBrush
23         {
24             set
25             {
26                 base.SetValue(ShareButton.EnterBrushProperty, value);
27             }
28             get
29             {
30                 return base.GetValue(ShareButton.EnterBrushProperty) as Brush;
31             }
32         }
33         static ShareButton()
34         {
35             //注册属性
36             ShareButton.MoveBrushProperty = DependencyProperty.Register("MoveBrush", typeof(Brush), typeof(ShareButton), new PropertyMetadata(null));
37             ShareButton.EnterBrushProperty = DependencyProperty.Register("EnterBrush", typeof(Brush), typeof(ShareButton), new PropertyMetadata(null));
38             FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(ShareButton), new FrameworkPropertyMetadata(typeof(ShareButton)));
39         }
40         public ShareButton()
41         {
42             base.Content = "";
43         }
44     }

        从代码中可以看出,DependencyProperty MoveBrushProperty是个依赖属性,MoveBrush提供了对MoveBrushProperty属性的封装。那问题来了,什么是依赖属性?

        传统中.net framework中的属性,也被称为CLR属性,它在实例化的时候会分配数据存储空间。而包含依赖属性的对象被称为依赖对象,它在实例化的时候并不会直接分配数据存储空间,而是保留了这样的分配能力。如果说,我们直接给这个依赖属性赋值的话,它才开始分配空间,如果它依赖于其它对象的话,也就是说,这个依赖属性的值是从其它对象那儿”拿来”的话,就不用分配内存了,而是需要绑定。

       我查看了下Button的类层次结构:

        

 

Button: ButtonBase:ContentControl,因此我们自定义的 ShareButton继承自Button,自然是依赖对象,所以理所当然地可以自定义依赖属性了。

再来看看这个控件如何使用?

1、添加命名空间: xmlns:s="clr-namespace:ShareControl;assembly=ShareControl"

2、这是一个登陆按钮

 1  <s:ShareButton x:Name="btnLogin" Click="btnLogin_Click"  FontSize="14"  Content="登  录"  Width="235" Height="33" Foreground="White" Cursor="Hand"  IsDefault="True">
 2 
 3                 <s:ShareButton.EnterBrush>
 4                     <ImageBrush ImageSource="Skin/Icon/login_button.png"/>
 5                 </s:ShareButton.EnterBrush>
 6                 <s:ShareButton.MoveBrush>
 7                     <ImageBrush ImageSource="Skin/Icon/login_button_hover.png"/>
 8                 </s:ShareButton.MoveBrush>
 9                 <s:ShareButton.Background>
10                     <ImageBrush ImageSource="Skin/Icon/login_button.png"/>
11                 </s:ShareButton.Background>
12             </s:ShareButton>

运行效果:

鼠标经过时,是另外一个背景

自定义按钮长得这么漂亮,肯定需要样式的支持:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ShareControl">

    <Style x:Key="{x:Type local:ShareButton }" TargetType="{x:Type local:ShareButton}">

        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>

        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ShareButton}">
                    <Border Name="border" BorderBrush="{TemplateBinding Control.BorderBrush}" BorderThickness="{TemplateBinding Control.BorderThickness}" SnapsToDevicePixels="True" Width="{TemplateBinding FrameworkElement.Width}" Height="{TemplateBinding FrameworkElement.Height}" Background="{TemplateBinding Control.Background}">
                        <ContentPresenter Name="contentPresenter" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Focusable="False" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="UIElement.IsMouseOver" Value="True">
                            <Setter TargetName="border" Value="{Binding MoveBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Border.Background" />
                        </Trigger>
                        <Trigger Property="ButtonBase.IsPressed" Value="True">
                            <Setter TargetName="border"  Value="{Binding EnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Border.Background" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

 

posted @ 2017-10-27 18:47  micDavid  阅读(387)  评论(0编辑  收藏  举报