• 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>
  • 相关阅读:
    五大常用算法之一:分治算法
    【Redis实战】双写一致性问题和解决方案
    大厂面试官喜欢这样问Redis,双写一致性、并发竞争、线程模型,我整理好了
    布隆过滤器的原理以及使用场景
    死磕 Redis- 布隆过滤器
    布隆过滤器(Bloom Filter)原理及实现
    布隆过滤器(亿级数据过滤算法)
    Java防止SQL注入2(通过filter过滤器功能进行拦截)
    java项目中如何防止sql注入
    java如入防止sql注入
  • 原文地址:https://www.cnblogs.com/wangqiang3311/p/7744783.html
Copyright © 2020-2023  润新知