WPF自动定义控件一般有三种方式:
第一种是建立一个UserControl,这是最简单的方式,也是比较常用的方式。在这种方式中,可以直接使用VS的设计器进行UI的设计,并且可以直接添加事件处理函数,还可以为它设计对应的ViewMode。与一般的Window的设计没什么区别。
第二种是继承自Control类,这也是一种比较常用的方式。这种方式需要提供一个默认的ControlTemplate,并且使用该控件的开发者,可以为该控件提供新的ControlTemplate和DataTemplate。
第三种是继承自FrameWorkElement,这种方式是比较底层的设计新的UserControl的方法。需要重写Render方法类渲染UserControl。在之后的随笔中会添加,本随笔针对第二种情况。
1. 在Themes---> Generic.xaml文件中提供默认的ControlTemplate,文件夹名Themes和Generic.xaml是固定的,不可更改。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:TimeLine"> <Style TargetType="{x:Type local:TimeLineControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:TimeLineControl}"> <StackPanel Orientation="Horizontal"> <TextBlock x:Name="PART_DateTimeTextBox" Text="{TemplateBinding DateTimeMsg}"/> <TextBlock x:Name="PART_ContentTextBox" Text="{TemplateBinding ContentMsg}"/> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
2. 提供后台的逻辑代码
namespace TimeLine { [TemplatePart(Name = TimeLineControl.ElementDateTimeTextBox, Type = typeof(TextBlock))] [TemplatePart(Name = TimeLineControl.ElementContentTextBox, Type = typeof(TextBlock))] public class TimeLineControl : Control { private const string ElementDateTimeTextBox = "PART_DateTimeTextBox"; private const string ElementContentTextBox = "PART_ContentTextBox"; TextBlock dateTimeTB = null; TextBlock contentMsgTB = null; public TimeLineControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeLineControl), new FrameworkPropertyMetadata(typeof(TimeLineControl))); ContentMsg = "Hello World"; DateTimeMsg = "DateTime"; } public override void OnApplyTemplate() { base.OnApplyTemplate(); dateTimeTB = GetTemplateChild(ElementDateTimeTextBox) as TextBlock; contentMsgTB = GetTemplateChild(ElementContentTextBox) as TextBlock; } /// <summary> /// Registers a dependency property as backing store for the Content property /// </summary> public static readonly DependencyProperty ContentMsgProperty = DependencyProperty.Register("ContentMsg", typeof(object), typeof(TimeLineControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsParentMeasure)); /// <summary> /// Gets or sets the Content. /// </summary> /// <value>The Content.</value> public object ContentMsg { get { return (object)GetValue(ContentMsgProperty); } set { SetValue(ContentMsgProperty, value); } } public static readonly DependencyProperty DateTimeMsgProperty = DependencyProperty.Register("DateTimeMsg", typeof(object), typeof(TimeLineControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsParentMeasure)); public object DateTimeMsg { get { return (object)GetValue(DateTimeMsgProperty); } set { SetValue(DateTimeMsgProperty, value); } } } }
自定义控件时,常用的基类有:
- UIElement - The most lightweight base class to start from. It has support for LIFE - Layout, Input, Focus and Events.
- FrameworkElement - Derives from UIElement and adds support for styling, tooltips and context menus. It is first base class that takes part in the logical tree and so it supports data binding and resource lookup.
- Control - is the most common base class for controls (its name speaks for itself). It supports templates and adds some basic properties as
Foreground
,Background
orFontSize
. - ContentControl - is a control that has an additional
Content
property. This is often used for simple containers. - HeaderedContentControl - is a control that has an
Content
and aHeader
property. This is used for controls with a header like Expander, TabControl, GroupBox,... - ItemsControl - a control that has an additional
Items
collection. This is a good choice for controls that display a dynamic list of items without selection. - Selector - an ItemsControl whose items can be indexed and selected. This is used for ListBox, ComboBox, ListView, TabControl...
- RangeBase - is the base class for controls that display a value range like Sliders or ProgressBars. It adds an
Value
,Minimum
andMaximum
property.