博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF 构建无外观(Lookless)控件
阅读量:4967 次
发布时间:2019-06-12

本文共 4526 字,大约阅读时间需要 15 分钟。

原文:

构建一个用户可以使用Template属性设置外观的WPF控件需要以下几步

  1. 1、继承自System.Windows.Controls.Control
    2、设置DefaultStyleKeyProperty
    3、实现控件功能
  2. 4、定义默认Sytle
  3. 5、添加ThemeInfo
    我借用一个时钟的控件例子,讲解以下每一个步骤
  4. 第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
), typeof(Clock));
55: 
56:     protected virtual void OnDateTimeChanged(DateTime oldValue, DateTime newValue)
57:     {
58:         RoutedPropertyChangedEventArgs
args = new RoutedPropertyChangedEventArgs
(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: 
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:     
8:         
9:             
10:                 
11:                     
12:                 
13:             
14:         
15:     
16: 
这里要注意TargetType的使用。到这里控件还是不能找到默认的模板,还需要下面的最后一步

 

  1. 第5步 添加ThemeInfo

 

最后还需要在AssemblyInfo.cs文件中加入ThemeInfo信息,在文件中加入以下特性

1: [assembly: ThemeInfo(
2:     ResourceDictionaryLocation.None,
3:     ResourceDictionaryLocation.SourceAssembly
4: )]

 

  1. 附注

 

如果需要在模板中使用特定的元素名,来或许模板中的某个特定控件,还有几个地方需要注意。

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

这个内容可以参考

  1. 参考资料

 

posted on
2019-04-05 00:17 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/10657680.html

你可能感兴趣的文章
02号团队-团队任务3:每日立会(2018-12-05)
查看>>
SQLite移植手记1
查看>>
js05-DOM对象二
查看>>
mariadb BINLOG_FORMAT = STATEMENT 异常
查看>>
C3P0 WARN: Establishing SSL connection without server's identity verification is not recommended
查看>>
iPhone在日本最牛,在中国输得最慘
查看>>
动态方法决议 和 消息转发
查看>>
js 基础拓展
查看>>
C#生成随机数
查看>>
Android应用程序与SurfaceFlinger服务的连接过程分析
查看>>
Java回顾之多线程
查看>>
机电行业如何进行信息化建设
查看>>
9、总线
查看>>
Git 笔记 - section 1
查看>>
2018 Multi-University Training Contest 10 - Count
查看>>
HDU6203 ping ping ping
查看>>
《人人都是产品经理》书籍目录
查看>>
如何在git bash中运行mysql
查看>>
OO第三阶段总结
查看>>
构建之法阅读笔记02
查看>>