阅读 156

WPF自定义按钮Button控件(一)

一、背景

在项目开发过程中,很多时候系统自带的控件并不能很好的满足我们的开发需求,这个时候就需要使用到自定义控件。由于工作中遇到的项目会涉及到很多的按钮控件,因此也特意写了一个自定义的按钮来满足项目的开发需求,在这里记录一下实现的过程。

二、目标

1、在项目中,界面部分都是由美工进行设计,然后再将UI进行裁图,交到我手上的就是一堆的png图片,然后我再拿着这些图片来还原出美工的设计的界面。
2、一个按钮的素材一般都是包含两个png图片,一个是未按下状态的图片,一个按下状态的图片。用系统自带的Button实现时,代码如下,感觉一个按钮就一大片代码,看起来也忒难受了。

<Button x:Name="button" Width="200" Height="60" Click="button_click">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}" >
                        <Grid>
                            <Rectangle x:Name="rec" Fill="{StaticResource Btn_u}"/>
                        Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="rec" Property="Fill" Value="{StaticResource Btn_d}"/>
                            Trigger>
                        ControlTemplate.Triggers>
                    ControlTemplate>
                Setter.Value>
            Setter>
        Style>
    Button.Style>
Button>

3、所以初步的目标可以先确定出来,自定义按钮得支持直接设置按下和非按下的背景图。还有就是按钮也支持设置成普通按钮(按下后自动弹起)和自锁按钮(相当于CheckBox)两种模式。话不多说,直接动手开干。

三、功能实现

1、新建自定义控件

打开已经创建好的WPF工程文件,选中项目然后右键选择添加一个用户控件,控件的名称自行按照自己的习惯来定,不要aaa、bbb之类的就行。创建完之后就大概这个样子,接着我们开始实现我们想要的功能。

2、添加依赖属性

首先改造一下控件的界面部分,改完后代码如下,主要就是监听一下鼠标的按下和弹起事件

<UserControl x:Class="ButtonDemo.Control.MyRepeatButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ButtonDemo.Control"
             mc:Ignorable="d" 
             x:Name="myInstance" d:DesignHeight="450" d:DesignWidth="800">
    <Grid x:Name="grid" Width="{Binding ElementName=myInstance,Path=Width}" Height="{Binding ElementName=myInstance,Path=Height}"
          PreviewMouseLeftButtonDown="grid_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="grid_PreviewMouseLeftButtonUp">

    Grid>
UserControl>

然后转到后台代码部分,定义和注册一些想要的属性,这里我先定义和注册了四个属性
(1)Switch:按钮状态属性,y为按下状态,n为未按下状态
(2)HasRepeat:是否为自锁按钮,true为自锁按钮,false为普通按钮
(3)SelectedBrush:按钮按下状态的背景
(4)UnSelectedBrush:按钮未按下状态的背景

public string Switch
{
    get { return (string)GetValue(SwitchProperty); }
    set { SetValue(SwitchProperty, value); }
}
public static readonly DependencyProperty SwitchProperty =
    DependencyProperty.Register("Switch", typeof(string), typeof(MyRepeatButton),
        new FrameworkPropertyMetadata("n", FrameworkPropertyMetadataOptions.AffectsRender, OnRectangleColorChanged));

private static void OnRectangleColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var j = (MyRepeatButton)d;
    string s = (string)e.NewValue;
    string oldValue = (string)e.OldValue;

    if (s == oldValue)
    {
        return;
    }
    if (s == "y")
    {
        j.grid.Background = (Brush)j.GetValue(SelectedBrushProperty);
    }
    else
    {
        j.grid.Background = (Brush)j.GetValue(UnSelectedBrushProperty);
    }
}

public bool HasRepeat
{
    get { return (bool)GetValue(HasRepeatProperty); }
    set { SetValue(HasRepeatProperty, value); }
}
public static readonly DependencyProperty HasRepeatProperty =
    DependencyProperty.Register("HasRepeat", typeof(bool), typeof(MyRepeatButton),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));

public Brush SelectedBrush
{
    get { return (Brush)GetValue(SelectedBrushProperty); }
    set { SetValue(SelectedBrushProperty, value); }
}
public static readonly DependencyProperty SelectedBrushProperty =
    DependencyProperty.Register("SelectedBrush", typeof(Brush), typeof(MyRepeatButton),
        new FrameworkPropertyMetadata(Brushes.Green, FrameworkPropertyMetadataOptions.AffectsRender, OnSelectedChanged));

public Brush UnSelectedBrush
{
    get { return (Brush)GetValue(UnSelectedBrushProperty); }
    set { SetValue(UnSelectedBrushProperty, value); }
}
public static readonly DependencyProperty UnSelectedBrushProperty =
    DependencyProperty.Register("UnSelectedBrush", typeof(Brush), typeof(MyRepeatButton),
        new FrameworkPropertyMetadata(Brushes.Red, FrameworkPropertyMetadataOptions.AffectsRender, OnUnSelectedChanged));

private static void OnSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Brush newValue = (Brush)e.NewValue;
    var s = (MyRepeatButton)d;
    if (newValue != null)
    {
        if (s.Switch == "y")
        {
            s.grid.Background = newValue;
        }
    }
}

private static void OnUnSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Brush newValue = (Brush)e.NewValue;
    var s = (MyRepeatButton)d;
    if (newValue != null)
    {
        if (s.Switch == "n")
        {
            s.grid.Background = newValue;
        }
    }
}

接着在鼠标的按下和弹起事件中增加逻辑代码即可

private void grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (Switch == "n")
    {
        Switch = "y";
    }
    else if (Switch == "y")
    {
        if (HasRepeat)
        {
            Switch = "n";
        }
    }
}

private void grid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (!HasRepeat)
    {
        Switch = "n";
    }
}

到这里我们的自定义按钮就算是初步完成了,来用起来看看能不能达到预期的效果

3、使用自定义按钮控件

首先找两种按钮的图片添加到工程目录中,比如我找了这两张图片来测试,然后在App.xaml文件中添加一下

 

 

 

 

<Application x:Class="ButtonDemo.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ButtonDemo"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ImageBrush x:Key="Btn_u" ImageSource="images/Btn_u.png"/>
        <ImageBrush x:Key="Btn_d" ImageSource="images/Btn_d.png"/>
    Application.Resources>
Application>

然后在主窗口添加我们自定义的按钮,一个设置为普通按钮,一个为自锁按钮

<Window x:Class="ButtonDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:my="clr-namespace:ButtonDemo.Control"
        xmlns:local="clr-namespace:ButtonDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <my:MyRepeatButton Width="200" Height="80" HasRepeat="True"  Margin="10"
                               SelectedBrush="{StaticResource Btn_d}" UnSelectedBrush="{StaticResource Btn_u}"/>
            <my:MyRepeatButton Width="200" Height="80" HasRepeat="False" Margin="10"
                               SelectedBrush="{StaticResource Btn_d}" UnSelectedBrush="{StaticResource Btn_u}"/>
        StackPanel>
    Grid>
Window>

最终实现的效果如下

四、结束

1、关于自定义按钮的初步实现就暂时到这,目前这种简单的控件肯定还不能完全满足项目的需求,后续还会慢慢往里面加各种功能。
2、初学写博客,还望各位大佬多提宝贵意见,抱拳了!

原文:https://www.cnblogs.com/cong2312/p/15241255.html

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐