WPF自定义控件开发实例 - ColorPicker
开发环境:Win10 + VS2017 + .Net4.5
这个 ColorPicker 是<<WPF编程宝典:使用C#2012和.NET4.5>>这本书中的例子.这里我记录一下,主要是为了加深印象,防止以后要开发自定义控件的时候忘记一些基本的步骤,可以随时来查一下.
调到博文的最后可以先查看一下效果图.
建立ColorPicker类继承自 Control类

为什么继承自 Control,Control类继承自UIElement -> FrameworkElement -> ColorPicker,同时 Control 类提供了 Template 功能.通知WPF,将为控件提供新的样式.
方法是在静态构造函数中调用 OverrideMetadata()方法.static ColorPicker()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
}
编写控件逻辑,添加一些必要的属性|事件|方法 ...
重写 OnApplyTemplate 方法,为模板中的元素添加数据绑定或者关联事件处理程序
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("CornerRadius", 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(
"UseDynamicBorder", typeof(bool), typeof(ColorPicker),
new FrameworkPropertyMetadata(true, OnUseDynamicBorderChanged)); public static readonly RoutedEvent ColorChangedEvent = EventManager.RegisterRoutedEvent(
"ColorChangedEvent", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<Color>), typeof(ColorPicker));
public event RoutedPropertyChangedEventHandler<Color> ColorChanged
{
add { AddHandler(ColorChangedEvent, value); }
remove { RemoveHandler(ColorChangedEvent, value); }
} static ColorPicker()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
} public ColorPicker()
{
Loaded += (sender, args) =>
{
_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("PART_RedSlider") as RangeBase;
if (slider != null)
{
Binding binding = new Binding()
{
Path = new PropertyPath("Red"),
Source = this,
Mode = BindingMode.TwoWay
};
slider.SetBinding(RangeBase.ValueProperty, binding);
slider.Maximum = RGBMaxValue;
} slider = GetTemplateChild("PART_GreenSlider") 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("PART_BlueSlider") 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("PART_PreviewBrush") as SolidColorBrush;
if (brush != null)
{
Binding bd = new Binding
{
Path = new PropertyPath(nameof(brush.Color)),
Source = brush,
Mode = BindingMode.OneWayToSource
};
SetBinding(ColorPicker.ColorProperty, bd);
}
} }
}
差不多就是这样一个简单的ColorPicker就出来了.另外增加一个UseDynamicBorder,来控制控件边框的颜色是否动态改变.
看一下效果图

</div>
WPF自定义控件开发实例 - ColorPicker的更多相关文章
- TemplateBinding与Binding区别,以及WPF自定义控件开发的遭遇
在上一次的文章WPF OnApplyTemplate 不执行 或者执行滞后的疑惑谈到怎么正确的开发自定义控件,我们控件的样式中,属性的绑定一般都是用TemplateBinding来完成,如下一个基本的 ...
- WPF和Expression Blend开发实例:一个样式实现的数字输入框
原文:WPF和Expression Blend开发实例:一个样式实现的数字输入框 今天来一个比较奇淫技巧的手法,很少人用,同时也不推荐太过频繁的使用. 先上样式: <Style x:Key=&q ...
- WPF开发实例——仿QQ登录界面
原文:WPF开发实例--仿QQ登录界面 版权声明:本文为博主原创文章,如需转载请标明转载地址 http://blog.csdn.net/u013981858 https://blog.csdn.net ...
- WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展
一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...
- WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享
系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...
- WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...
- WPF自定义控件与样式(15)-终结篇
原文:WPF自定义控件与样式(15)-终结篇 系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与 ...
- WPF自定义控件创建
WPF自定义控件创建 本文简单的介绍一下WPF自定义控件的开发. 首先,我们打开VisualStudio创建一个WPF自定义控件库,如下图: 然后,我们可以看到创建的解决方案如下: 在解决方案中,我们 ...
- 【转】WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...
随机推荐
- 专访UI中国认证设计师卤大湿 | 一位UI大师关于UI设计的思考
现如今,设计师可以说是一个自带光环的Title,很多深藏不漏的UI设计师们都在以自己的方式为产品设计做出贡献,卤大湿便是这其中之一. 精分青年卤大湿,这个在UI中国上是张酷酷的鲁迅头像的UI设计师,是 ...
- STL基础1:vector
#include <iostream> #include <vector> #include <algorithm> #include <numeric> ...
- .net写本地文件的一个方法
整理代码,.net在本地写html文件的一个方法,代码如下 public static void WriteFile(string FilePath, string FileInfo, string ...
- [C#]WinForm动态删除控件 Controls.Remove()
今天遇到一个奇怪的问题,在WinForm内动态添加Button后再动态的移除,发生稀奇古怪的现象,Button控件只被规律的移除,没有完全移除 foreach (Control c in this.C ...
- 关于ueditor 在struts2 中 上传图片 ,未找到上传文件 问题的解决方法
问题原因: ueditor 上传图片需请求imageUp.jsp文件,struts2 自带的拦截器(/*)把所有请求的文件都做了处理,所以导致无法上传图片. 解决方法: 方法一:自定义拦截器,让它在请 ...
- 正则表达式,re模块
一.正则表达式 正则表达式 : 匹配字符串,一般用于爬取数据. 正则表达式查询网址 : http://tool.chinaz.com/regex/?qq-pf-to=pcqq.group 1.元字符( ...
- 796. Rotate String
class Solution { public: bool rotateString(string A, string B) { if(A.length()==B.length()&& ...
- ios label的一些设置
一.根据文本长度设置label的宽高和字体大小 NSString *str = @"天将降大任于斯人也,必先苦其心志.天将降大任于斯人也,必先苦其心志."; CGRect ...
- 2018.11.09 bzoj1706: relays 奶牛接力跑(倍增+floyd)
传送门 倍增+floyd板子题. 先列出状态fi,j,kf_{i,j,k}fi,j,k表示经过iii条边从jjj到kkk的最短路. 然后发现可以用fi−1,j,kf_{i-1,j,k}fi−1,j, ...
- understand试用笔记一阅读VS2010项目
一.查看vs2010项目 打开understand,File—New—Project...—Next—Next [向导第三步,选“Import Visual Sudio project files”] ...