在项目开发过程中,很多时候系统自带的控件并不能很好的满足我们的开发需求,这个时候就需要使用到自定义控件。由于工作中遇到的项目会涉及到很多的按钮控件,因此也特意写了一个自定义的按钮来满足项目的开发需求,在这里记录一下实现的过程。
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)两种模式。话不多说,直接动手开干。
打开已经创建好的WPF工程文件,选中项目然后右键选择添加一个用户控件,控件的名称自行按照自己的习惯来定,不要aaa、bbb之类的就行。创建完之后就大概这个样子,接着我们开始实现我们想要的功能。
首先改造一下控件的界面部分,改完后代码如下,主要就是监听一下鼠标的按下和弹起事件
<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"; } }
到这里我们的自定义按钮就算是初步完成了,来用起来看看能不能达到预期的效果
首先找两种按钮的图片添加到工程目录中,比如我找了这两张图片来测试,然后在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