一、背景
在項目開發過程中,很多時候系統自帶的控件並不能很好的滿足我們的開發需求,這個時候就需要使用到自定義控件。由於工作中遇到的項目會涉及到很多的按鈕控件,因此也特意寫了一個自定義的按鈕來滿足項目的開發需求,在這里記錄一下實現的過程。
二、目標
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、初學寫博客,還望各位大佬多提寶貴意見,抱拳了!