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、初學寫博客,還望各位大佬多提寶貴意見,抱拳了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM