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());
        }

猜你喜欢

转载自blog.csdn.net/m0_37655091/article/details/84286079