WPF 构建无外观(Lookless)控件
构建一个用户可以使用Template属性设置外观的WPF控件需要以下几步
- 1、继承自System.Windows.Controls.Control
2、设置DefaultStyleKeyProperty
3、实现控件功能 - 4、定义默认Sytle
- 5、添加ThemeInfo
我借用一个时钟的控件例子,讲解以下每一个步骤 第1步 继承自System.Windows.Controls.Control
我们的自定义控件继承自System.Windows.Controls.Control,如果有更特别的控件,也可以继承自更复杂的控件。
类声明
1: public class Clock : Control
2: {
3: }
第2步 设置DefaultStyleKeyProperty
无外观的控件需要在静态构造函数中设置DefaultStyleKeyProperty,这样它会去在themes/generic.xaml的文件获取默认的样式。
1: static Clock()
2: {
3: DefaultStyleKeyProperty.OverrideMetadata(typeof(Clock), new FrameworkPropertyMetadata(typeof(Clock)));
4: }
第3步 实现控件功能
这一步没什么特别的,就是内部有个DateTime类型和一个DispatcherTimer,完成一个时钟的功能
1: public class Clock : Control
2: {
3: private DispatcherTimer timer;
4:
5: static Clock()
6: {
7: DefaultStyleKeyProperty.OverrideMetadata(typeof(Clock), new FrameworkPropertyMetadata(typeof(Clock)));
8: }
9:
10: protected override void OnInitialized(EventArgs e)
11: {
12: base.OnInitialized(e);
13:
14: UpdateDateTime();
15:
16: timer = new DispatcherTimer();
17: timer.Interval = TimeSpan.FromMilliseconds(1000 - DateTime.Now.Millisecond);
18: timer.Tick += new EventHandler(Timer_Tick);
19: timer.Start();
20: }
21:
22: private void Timer_Tick(object sender, EventArgs e)
23: {
24: UpdateDateTime();
25:
26: timer.Interval = TimeSpan.FromMilliseconds(1000 - DateTime.Now.Millisecond);
27: timer.Start();
28: }
29:
30: private void UpdateDateTime()
31: {
32: this.DateTime = System.DateTime.Now;
33: }
34:
35: public DateTime DateTime
36: {
37: get
38: {
39: return (DateTime)GetValue(DateTimeProperty);
40: }
41: private set
42: {
43: SetValue(DateTimeProperty, value);
44: }
45: }
46:
47: public static DependencyProperty DateTimeProperty = DependencyProperty.Register(
48: "DateTime",
49: typeof(DateTime),
50: typeof(Clock),
51: new PropertyMetadata(DateTime.Now, new PropertyChangedCallback(OnDateTimeInvalidated)));
52:
53: public static readonly RoutedEvent DateTimeChangedEvent =
54: EventManager.RegisterRoutedEvent("DateTimeChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<DateTime>), typeof(Clock));
55:
56: protected virtual void OnDateTimeChanged(DateTime oldValue, DateTime newValue)
57: {
58: RoutedPropertyChangedEventArgs<DateTime> args = new RoutedPropertyChangedEventArgs<DateTime>(oldValue, newValue);
59: args.RoutedEvent = Clock.DateTimeChangedEvent;
60: RaiseEvent(args);
61: }
62:
63: private static void OnDateTimeInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e)
64: {
65: Clock clock = (Clock)d;
66:
67: DateTime oldValue = (DateTime)e.OldValue;
68: DateTime newValue = (DateTime)e.NewValue;
69:
70: clock.OnDateTimeChanged(oldValue, newValue);
71: }
72: }
第4步 定义默认Sytle
如上所述,我们还需要一个默认的Template,它写在themes/generic.xaml文件中,这个文件可能需要自己创建
1: <ResourceDictionary
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:local="clr-namespace:CustomControlLibrary"
5: >
6:
7: <Style TargetType="{x:Type local:Clock}">
8: <Setter Property="Template">
9: <Setter.Value>
10: <ControlTemplate TargetType="{x:Type local:Clock}">
11: <TextBlock Text="{Binding Path=DateTime, RelativeSource={RelativeSource TemplatedParent}}" />
12: </ControlTemplate>
13: </Setter.Value>
14: </Setter>
15: </Style>
16: </ResourceDictionary>
这里要注意TargetType的使用。到这里控件还是不能找到默认的模板,还需要下面的最后一步
第5步 添加ThemeInfo
最后还需要在AssemblyInfo.cs文件中加入ThemeInfo信息,在文件中加入以下特性
1: [assembly: ThemeInfo(
2: ResourceDictionaryLocation.None,
3: ResourceDictionaryLocation.SourceAssembly
4: )]
附注
如果需要在模板中使用特定的元素名,来或许模板中的某个特定控件,还有几个地方需要注意。
1、模板内的Name最好以PART开头,好的名称类似于PART_TextBox
2、获取Template中控件的代码,需要重载OnApplyTemplate()方法,可以使用GetTemplateChild方法获取,如下
1: public override void OnApplyTemplate()
2: {
3: base.OnApplyTemplate();
4:
5: //从模板中获取名称为PART_PresentationTextBox的TextBox
6: _presentationTextBox = GetTemplateChild("PART_PresentationTextBox") as TextBox;
7: if(_presentationTextBox != null)
8: {
9: //对_presentationTextBox进行操作
10: }
11: }
3、在控件类添加TemplatePart
1: [TemplatePart(Name = "PART_PresentationTextBox", Type = typeof(TextBox))]
2: public class TimeSpanPicker:Control
这个内容可以参考https://gitcafe.com/atskyline/WPFTimeSpanPickerControl
参考资料
http://www.codeproject.com/Articles/14340/Creating-a-look-less-custom-control-in-WPF
http://www.codeproject.com/Articles/35444/Defining-the-Default-Style-for-a-Lookless-Control
WPF 构建无外观(Lookless)控件的更多相关文章
- [转]WPF 构建无外观(Lookless)控件
构建一个用户可以使用Template属性设置外观的WPF控件需要以下几步 1.继承自System.Windows.Controls.Control 2.设置DefaultStyleKeyPropert ...
- 【WPF学习】第六十四章 构建基本的用户控件
创建一个简单用户控件是开始自定义控件的好方法.本章主要介绍创建一个基本的颜色拾取器.接下来分析如何将这个控件分解成功能更强大的基于模板的控件. 创建基本的颜色拾取器很容易.然而,创建自定义颜色拾取器仍 ...
- WPF Timeline简易时间轴控件的实现
原文:WPF Timeline简易时间轴控件的实现 效果图: 由于整个控件是实现之后才写的教程,因此这里记录的代码是最终实现后的,前后会引用到其他的一些依赖属性或者代码,需要阅读整篇文章. 1.确定T ...
- .Net中使用无闪刷新控件时提示框不显示
今天做提示框的时候一直不显示,让我郁闷好久,晚上吃饭的时候问了同事一下,他给了一个思路, 他说可能是因为由于页面中的无闪刷新导致的结果:百度了一下真找到了解决方法 在页面中存在无闪刷新控件的时候提示框 ...
- WPF自定义控件(一)の控件分类
一.什么是控件(Controls) 控件是指对数据和方法的封装.控件可以有自己的属性和方法,其中属性是控件数据的简单访问者,方法则是控件的一些简单而可见的功能.控件创建过程包括设计.开发.调试(就是所 ...
- 基于 WPF 平台的 ActiveReports Viewer控件
ActiveReports 报表控件致力于为组织和个人提供最出色的报表解决方案,多年来ActiveReports已经提供了 Windows Forms.Web.Silverlight和Flash平台的 ...
- WPF不同线程之间的控件的访问
原文:WPF不同线程之间的控件的访问 WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public voi ...
- WindowsXamlHost:在 WPF 中使用 UWP 的控件(Windows Community Toolkit)
Windows Community Toolkit 再次更新到 5.0.以前可以在 WPF 中使用有限的 UWP 控件,而现在有了 WindowsXamlHost,则可以使用更多 UWP 原生控件了. ...
- WPF 动画:同为控件不同命 - 简书
原文:WPF 动画:同为控件不同命 - 简书 1. 及格与优秀 读大学的时候,有一门课的作业是用 PPT 展示. 但是我们很多同学都把 PPT 当做 Word 来用,就单纯地往里面堆文字. 大家都单纯 ...
随机推荐
- ZT acct 中文man页面(1)
acct 中文man页面(1) 2011-08-18 13:57 佚名 博客转载 我要评论(0) 字号:T | T 如果在内核编译时开启了进程记账选项(CONFIG_BSD_PROCESS_ACCT) ...
- 一个程序猿试用有道云笔记VIP功能体验
熟悉我的朋友应该知道,我有一个微信公众号,叫做"汪子熙", 我会定期在上面推送技术文章. 而我绝大多数技术文章都是在每天上下班的地铁上用手机写的,然后到家后同步到电脑上,进行发表. ...
- js、Jquery处理自动计算的输入框事件
js在处理的时候可以使用oninput去获取当前输入框输入的值, jquery的时候使用了keypress和keydown但是发现都不能在输入后触发事件去获取输入框的值,这时候需要使用 ‘input ...
- Class<T>和Class<?>区别
Class<T>在实例化的时候,T要替换成具体类Class<?>它是个通配泛型,?可以代表任何类型
- PAML学习一
前言 模式识别起源于工程,而机器学习从计算机科学中产生.然而这两者被看做同一领域的两方面,过去十年里他们获得了极大的发展.特别是,贝叶斯方法已经发展成主流,而图模型已经被融入用于描述和应用概率模型的通 ...
- 测试Storm的多源头锚定
过程, Spout 发送msgid 1-10 一级Bolt, msgid1的tuple做为基本组合tuple, 其他8个和一组合, 然后发送给二级Bolt, 同时单个msgid对应的tuple都ack ...
- 运用Xdebug调试和优化PHP程序
什么是Xdebug? Xdebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况.Xdebug现在的最新版本是xdebug 2.0.0beta ...
- LinQ 简介
LinQ是3.0新加的语法.用起来比较方便,我们可以使用较简单的方法来过滤数据和处理数据. 使用场景: 可以看到LINQ使用场景还是很多的.现在写项目基本都会用到. 在出现委托之前,我们来查找对象 在 ...
- js邮箱验证,身份证验证,正则表达式
邮箱验证: html部分: 邮箱验证:<input type="text" id="mail" value="" / onkeyup= ...
- 自动诊断档案库(ADR)学习
(1)ADR概述 Oracle 11g的FDI(Fault Diagnosability Infrastructure)是自动化诊断方面的一个增强,其核心组件为自动诊断库(Automatic Diag ...