开发环境:Win10 + VS2017 + .Net4.5

这个 ColorPicker 是<<WPF编程宝典:使用C#2012和.NET4.5>>这本书中的例子.这里我记录一下,主要是为了加深印象,防止以后要开发自定义控件的时候忘记一些基本的步骤,可以随时来查一下.

调到博文的最后可以先查看一下效果图.

  1. 建立ColorPicker类继承自 Control



    为什么继承自 Control,Control类继承自UIElement -> FrameworkElement -> ColorPicker,同时 Control 类提供了 Template 功能.

  2. 通知WPF,将为控件提供新的样式.

    方法是在静态构造函数中调用 OverrideMetadata()方法.

    static ColorPicker()
    {
    DefaultStyleKeyProperty.OverrideMetadata(
    typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
    }
  3. 编写控件逻辑,添加一些必要的属性|事件|方法 ...

  4. 重写 OnApplyTemplate 方法,为模板中的元素添加数据绑定或者关联事件处理程序

  5. ColorPicker类的完整代码:

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    using System.Windows.Data;
    using System.Windows.Media; namespace Demo.DIYControl.Controls.DeepInDIY

    {

    [TemplatePart(Name = RedSliderName,Type = typeof(RangeBase))]

    [TemplatePart(Name = GreenSliderName, Type = typeof(RangeBase))]

    [TemplatePart(Name = BlueSliderName, Type = typeof(RangeBase))]

    [TemplatePart(Name = PreviewBrushName, Type = typeof(SolidColorBrush))]

    public class ColorPicker:Control

    {

    private const string RedSliderName = "PART_RedSlider";

    private const string GreenSliderName = "PART_GreenSlider";

    private const string BlueSliderName = "PART_BlueSlider";

    private const string PreviewBrushName = "PART_PreviewBrush";
         private Brush _initializeBorderBrush;
    
         public const byte RGBMaxValue = 255;
    
         public byte Red
    {
    get { return (byte)GetValue(RedProperty); }
    set { SetValue(RedProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Red. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty RedProperty =
    DependencyProperty.Register(
    nameof(Red), typeof(byte), typeof(ColorPicker),
    new FrameworkPropertyMetadata(OnColorRGBChanged)); public byte Green
    {
    get { return (byte)GetValue(GreenProperty); }
    set { SetValue(GreenProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Green. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty GreenProperty =
    DependencyProperty.Register(
    nameof(Green), typeof(byte), typeof(ColorPicker),
    new FrameworkPropertyMetadata(OnColorRGBChanged)); public byte Blue
    {
    get { return (byte)GetValue(BlueProperty); }
    set { SetValue(BlueProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Blue. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BlueProperty =
    DependencyProperty.Register(
    nameof(Blue), typeof(byte), typeof(ColorPicker),
    new FrameworkPropertyMetadata(OnColorRGBChanged)); public Color Color
    {
    get { return (Color)GetValue(ColorProperty); }
    set { SetValue(ColorProperty, value); }
    }
    // Using a DependencyProperty as the backing store for Color. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColorProperty =
    DependencyProperty.Register(nameof(Color), typeof(Color),
    typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.Black,OnColorChanged)); public CornerRadius CornerRadius
    {
    get { return (CornerRadius)GetValue(CornerRadiusProperty); }
    set { SetValue(CornerRadiusProperty, value); }
    }
    // Using a DependencyProperty as the backing store for CornerRadius. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CornerRadiusProperty =
    DependencyProperty.Register(&quot;CornerRadius&quot;, typeof(CornerRadius), typeof(ColorPicker),
    new FrameworkPropertyMetadata(default(CornerRadius))); public bool UseDynamicBorder
    {
    get { return (bool)GetValue(UseDynamicBorderProperty); }
    set { SetValue(UseDynamicBorderProperty, value); }
    }
    // Using a DependencyProperty as the backing store for UseDynamicBorder. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UseDynamicBorderProperty =
    DependencyProperty.Register(
    &quot;UseDynamicBorder&quot;, typeof(bool), typeof(ColorPicker),
    new FrameworkPropertyMetadata(true, OnUseDynamicBorderChanged)); public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent(
    &quot;ColorChangedEvent&quot;, RoutingStrategy.Bubble,
    typeof(RoutedPropertyChangedEventHandler&lt;Color&gt;), typeof(ColorPicker));
    public event RoutedPropertyChangedEventHandler&lt;Color&gt; ColorChanged
    {
    add { AddHandler(ColorChangedEvent, value); }
    remove { RemoveHandler(ColorChangedEvent, value); }
    } static ColorPicker()
    {
    DefaultStyleKeyProperty.OverrideMetadata(
    typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
    } public ColorPicker()
    {
    Loaded += (sender, args) =&gt;
    {
    _initializeBorderBrush = BorderBrush; //save initial borderbrush
    BorderBrush = UseDynamicBorder? new SolidColorBrush(Color) : BorderBrush;
    };
    } private static void OnColorRGBChanged(DependencyObject sender,
    DependencyPropertyChangedEventArgs args)
    {
    ColorPicker colorPicker = sender as ColorPicker;
    colorPicker = colorPicker ?? throw new ArgumentException(); Color color = colorPicker.Color;
    if (args.Property == RedProperty)
    color.R = (byte)args.NewValue;
    else if (args.Property == GreenProperty)
    color.G = (byte)args.NewValue;
    else if (args.Property == BlueProperty)
    color.B = (byte)args.NewValue; colorPicker.Color = color;
    } private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    ColorPicker colorPicker = d as ColorPicker;
    d = d ?? throw new ArgumentException();
    colorPicker.Red = colorPicker.Color.R;
    colorPicker.Green = colorPicker.Color.G;
    colorPicker.Blue = colorPicker.Color.B; //set border color
    if (colorPicker.UseDynamicBorder)
    colorPicker.BorderBrush = new SolidColorBrush(colorPicker.Color); colorPicker.RaiseEvent(
    new RoutedEventArgs(ColorChangedEvent, e.NewValue));
    } private static void OnUseDynamicBorderChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
    ColorPicker colorPicker = d as ColorPicker;
    colorPicker = colorPicker ?? throw new ArgumentException(); colorPicker.BorderBrush = (bool)args.NewValue ? new SolidColorBrush(colorPicker.Color) : colorPicker._initializeBorderBrush;
    } public override void OnApplyTemplate()
    {
    base.OnApplyTemplate(); RangeBase slider = GetTemplateChild(&quot;PART_RedSlider&quot;) as RangeBase;
    if (slider != null)
    {
    Binding binding = new Binding()
    {
    Path = new PropertyPath(&quot;Red&quot;),
    Source = this,
    Mode = BindingMode.TwoWay
    };
    slider.SetBinding(RangeBase.ValueProperty, binding);
    slider.Maximum = RGBMaxValue;
    } slider = GetTemplateChild(&quot;PART_GreenSlider&quot;) as RangeBase;
    if (slider != null)
    {
    Binding binding = new Binding()
    {
    Path = new PropertyPath(nameof(Green)),
    Source = this,
    Mode = BindingMode.TwoWay
    };
    slider.SetBinding(RangeBase.ValueProperty, binding);
    slider.Maximum = RGBMaxValue;
    } slider = GetTemplateChild(&quot;PART_BlueSlider&quot;) as RangeBase;
    if (slider != null)
    {
    Binding binding = new Binding()
    {
    Path = new PropertyPath(nameof(Blue)),
    Source = this,
    Mode = BindingMode.TwoWay
    };
    slider.SetBinding(RangeBase.ValueProperty, binding);
    slider.Maximum = RGBMaxValue;
    } SolidColorBrush brush = GetTemplateChild(&quot;PART_PreviewBrush&quot;) as SolidColorBrush;
    if (brush != null)
    {
    Binding bd = new Binding
    {
    Path = new PropertyPath(nameof(brush.Color)),
    Source = brush,
    Mode = BindingMode.OneWayToSource
    };
    SetBinding(ColorPicker.ColorProperty, bd);
    }
    } }

    }

  6. 差不多就是这样一个简单的ColorPicker就出来了.另外增加一个UseDynamicBorder,来控制控件边框的颜色是否动态改变.

    看一下效果图

  </div>

WPF自定义控件开发实例 - ColorPicker的更多相关文章

  1. TemplateBinding与Binding区别,以及WPF自定义控件开发的遭遇

    在上一次的文章WPF OnApplyTemplate 不执行 或者执行滞后的疑惑谈到怎么正确的开发自定义控件,我们控件的样式中,属性的绑定一般都是用TemplateBinding来完成,如下一个基本的 ...

  2. WPF和Expression Blend开发实例:一个样式实现的数字输入框

    原文:WPF和Expression Blend开发实例:一个样式实现的数字输入框 今天来一个比较奇淫技巧的手法,很少人用,同时也不推荐太过频繁的使用. 先上样式: <Style x:Key=&q ...

  3. WPF开发实例——仿QQ登录界面

    原文:WPF开发实例--仿QQ登录界面 版权声明:本文为博主原创文章,如需转载请标明转载地址 http://blog.csdn.net/u013981858 https://blog.csdn.net ...

  4. WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...

  5. WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享

    系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...

  6. WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...

  7. WPF自定义控件与样式(15)-终结篇

    原文:WPF自定义控件与样式(15)-终结篇 系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与 ...

  8. WPF自定义控件创建

    WPF自定义控件创建 本文简单的介绍一下WPF自定义控件的开发. 首先,我们打开VisualStudio创建一个WPF自定义控件库,如下图: 然后,我们可以看到创建的解决方案如下: 在解决方案中,我们 ...

  9. 【转】WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...

随机推荐

  1. setInterval与setTimeout 的区别

    setInterval在执行完一次代码之后,经过了那个固定的时间间隔,它还会自动重复执行代码,而setTimeout只执行一次那段代码     用法: setInterval("alert( ...

  2. OpenCV-图像通道转换问题

    OpenCV-MAT对象中使用plt.imshow(img[:,:,::-1])如何实现将第二轴反向? 系统平台:win10 x64 一.明确几个概念: 1.OpenCV内部每个通道并没有固定对应某种 ...

  3. IDEA如何把写好的java文件/项目打包成一个jar的文件

    一.命令行的方法 打开cmd,输入jar -cvf [打包后的文件名].jar [要打包的目录]. 二.IDEA的方法 写完一个java程序把它封装成一个jar的包  这样就可以在别的jar上面运行这 ...

  4. 核心一:IoC

    IoC 1.中文名称:控制反转 2.英文名称:(Inversion of Control) 3.IoC是什么? 3.1 IoC 完成的事情原先由程序员主动通过new 实例化对象事情,转交给Spring ...

  5. Java的函数重载必须满足的条件

    1.函数名相同 2.参数个数不同或者参数类型不同 3.函数重载和返回值类型无关 //函数的重载 public static void get() { System.out.println(" ...

  6. Tomcat服务器的安装和配置

    一.Tomcat下载 可以直接从Apache的网站上下载Tomcat(http://tomcat.apache.org/),进入首页后,在左边Download一栏可选择你要下载的版本,点击便可进入To ...

  7. math.net 拟合

    参考:http://blog.csdn.net/ztmsimon/article/details/50524392 在论坛中总看到有人在说Math.NET Iridium,查了一下,现在被整合到Mat ...

  8. highcharts x轴中文刻度太长换行

    xAxis: { type: 'category', title:null, gridLineWidth: 1, lineColor: "#50ae93", labels: { s ...

  9. 用JAVA实现大文件上传及显示进度信息

    一. 大文件上传基础描述: 各种WEB框架中,对于浏览器上传文件的请求,都有自己的处理对象负责对Http MultiPart协议内容进行解析,并供开发人员调用请求的表单内容. 比如: Spring 框 ...

  10. reload maven project' has encountered a proble" 问题

    由于重重原因,我取消maven的下载(可能是jar包没有公服镜像).导致重新打开sts 时发生异常. 在网上寻找到资料,发现需要删除${workspace}\.metadata\.plugins\or ...