WPF中的自定義控件

1.選擇正確的基類進行繼承,比較好的起點是UserControl

一般編譯爲DLL,以方便通用

2.創建依賴項屬性

1.先爲之定義靜態字段 如public static DependencyProperty ColorProperty;,

2.定義靜態構造函數,其中包含註冊依賴項屬性

3.將依賴項屬性封裝爲屬性以便訪問

4.定義回調函數以供修改對應的屬性和依賴項屬性值

3.定義路由事件

1.定義靜態路由事件

2.在靜態構造函數中註冊事件

3.創建.NET事件封裝器來公開事件

4.添加引發該事件的代碼,調用繼承自DependencyObject基類的RaiseEvent()方法

4.添加命令支持

下面是完整代碼:

xaml:

<UserControl x:Class="WpfApp1.ColorPicker"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="colorPicker">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Slider Name="sliderRed" Minimum="0" Maximum="255" Margin="{Binding ElementName=colorPicker,Path=Padding}"
                Value="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type UserControl}},Path=Red}"/>
        <Slider Grid.Row="1" Name="sliderGreed" Minimum="0" Maximum="255" Value="{Binding ElementName=colorPicker,Path=Green}"/>
        <Slider Grid.Row="2" Name="sliderBlue" Minimum="0" Maximum="255" Value="{Binding ElementName=colorPicker,Path=Blue}"/>
        <Rectangle Grid.Column="1" Grid.RowSpan="3" Width="50" Stroke="Black" StrokeThickness="1">
            <Rectangle.Fill>
                <SolidColorBrush Color="{Binding ElementName=colorPicker,Path=Color}"/>
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</UserControl>

後臺: 

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApp1
{
    /// <summary>
    /// 自定義控件顏色拾取器
    /// </summary>
    public partial class ColorPicker : UserControl
    {
        public static DependencyProperty ColorProperty;

        public static DependencyProperty RedProperty;
        public static DependencyProperty GreenProperty;
        public static DependencyProperty BlueProperty;

        public static readonly RoutedEvent ColorChangeEvent;

        Color? previousColor;

        public event RoutedPropertyChangedEventHandler<Color> ColorChanged
        {
            add { AddHandler(ColorChangeEvent, value); }
            remove { RemoveHandler(ColorChangeEvent, value); }
        }

        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }
        public byte Red
        {
            get { return (byte)GetValue(RedProperty); }
            set { SetValue(RedProperty, value); }
        }
        public byte Green
        {
            get { return (byte)GetValue(GreenProperty); }
            set { SetValue(GreenProperty, value); }
        }
        public byte Blue
        {
            get { return (byte)GetValue(BlueProperty); }
            set { SetValue(BlueProperty, value); }
        }

        public ColorPicker() => InitializeComponent();

        static ColorPicker()
        {
            //註冊依賴項屬性
            ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(ColorPicker),
                new FrameworkPropertyMetadata(Colors.Black, new PropertyChangedCallback(OnColorChanged)));
            RedProperty = DependencyProperty.Register("Red", typeof(byte), typeof(ColorPicker),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
            GreenProperty = DependencyProperty.Register("Green", typeof(byte), typeof(ColorPicker),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));
            BlueProperty = DependencyProperty.Register("Blue", typeof(byte), typeof(ColorPicker),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged)));

            ColorChangeEvent = EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble,
                typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));

            CommandManager.RegisterClassCommandBinding(typeof(ColorPicker), 
                new CommandBinding(ApplicationCommands.Undo, UndoCommand_Excuted, UndoCommand_CanExecute));
        }

        static void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ColorPicker colorPicker = sender as ColorPicker;
            e.CanExecute = colorPicker.previousColor.HasValue;//只要有以前緩存的顏色值就允許執行命令
        }

        static void UndoCommand_Excuted(object sender, ExecutedRoutedEventArgs e)
        {
            ColorPicker colorPicker = sender as ColorPicker;
            Color currentColor = colorPicker.Color;
            colorPicker.Color = (Color)colorPicker.previousColor;
        }

        static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Color newColor = (Color)e.NewValue;
            Color oldColor = (Color)e.OldValue;

            ColorPicker colorPicker = sender as ColorPicker;
            colorPicker.Red = newColor.R; colorPicker.Green = newColor.G; colorPicker.Blue = newColor.B;

            RoutedPropertyChangedEventArgs<Color> args = new RoutedPropertyChangedEventArgs<Color>(oldColor, newColor, ColorChangeEvent);
            colorPicker.RaiseEvent(args);
            colorPicker.previousColor = (Color)e.OldValue;
        }

        static void OnColorRGBChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ColorPicker colorPicker = sender as ColorPicker;
            Color color = colorPicker.Color;
            //修改對應的屬性和依賴項屬性值
            if (e.Property == RedProperty) color.R = (byte)e.NewValue;
            else if (e.Property == GreenProperty) color.G = (byte)e.NewValue;
            else if (e.Property == BlueProperty) color.B = (byte)e.NewValue;
            colorPicker.Color = color;
        }
    }
}

使用:

xaml:

<local:ColorPicker  x:Name="colorPicker" ColorChanged="ColorPicker_ColorChanged" Color="Beige" Margin="49,263,573,27"/>
        <Button x:Name="button" Content="Undo" HorizontalAlignment="Left" Margin="241,270,0,0" VerticalAlignment="Top" Width="75"
                Command="Undo" CommandTarget="{Binding ElementName=colorPicker}"/>

後臺:

        void ColorPicker_ColorChanged(object sender, RoutedPropertyChangedEventArgs<Color> e)
        {
            Console.WriteLine("新顏色是" + e.NewValue.ToString());
        }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章