1.概述
UWP允許開發者通過兩種方式創建自定義的控件:UserControl和TemplatedControl(模板化控件)。這個主題主要講述如何創建和理解模板化控件,目標是能理解模板化控件常見的知識點,並且可以創建擴展性良好的模板化控件。
1.1 ControlTemplate
UWP的控件有很多屬性,使用這些屬性可以為控件定制不同的外觀,例如將Button的Border變粗,Background改為紅色等,但通過這種改造控件,能做到的仍十分有限。
通過為控件賦予新的ControlTemplate,可以為控件創建全新的外觀。在下面的例子中,通過ControlTemplate將Button改成一個圓形按鈕。
<Button Content="Orginal" Margin="0,0,20,0"/>
<Button Content="Custom">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Stroke="DarkOrange" StrokeThickness="3" Fill="LightPink"/>
<ContentPresenter Margin="10,20" Foreground="White"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
ControlTemplate的內容是定義控件可視結構的XAML。有時,這段XAML的根元素包含VisualStateManager.VisualStateGroups附加屬性,用於定義不同狀態下控件的外觀變化。將ControlTemplate賦值到Control.Template即可改變控件的外觀。ControlTemplate的TargetType需要和使用它的控件匹配。
注意:UserControl不能使用ControlTemplate。
1.2 模板化控件
可以使用ControlTemplate的控件即為模板化控件(TemplatedControl),在UWP中,所有派生自Control的控件(除了UserControl)都是模板化控件,例如Button、ComboBox等,它們中的大部分都有默認的ControlTemplate。
模板化控件包含以下兩個部分:
- 代碼: 定義控件屬性及行為。
- DefaultStyle: 定義控件屬性默認樣式,包括屬性值及ControlTemplate。可以不存在DefaultStyle,所以某些場合會把模板化控件稱為“無外觀控件”。
2. 創建第一個模板化控件
下面介紹如何使用VisualStudio在一個新項目中創建一個模板化控件。
如圖所示,在“添加新項對”話框中選中TemplatedControl,名稱部分輸入“MyFirstControl”,點擊“添加”后VisualStudio會自動在項目中添加兩個文件:MyFirstControl.cs和Themes/Generic.xaml:
2.1 MyFirstControl.cs
public sealed class MyFirstControl : Control
{
public MyFirstControl()
{
this.DefaultStyleKey = typeof(MyFirstControl);
}
}
類文件負責定義控件的結構和行為。MyFirstControl.cs的代碼如圖所示,只包含一個構造函數及一句 this.DefaultStyleKey = typeof(MyFirstControl)。DefaultStyleKey是用於查找控件樣式的鍵,沒有這句代碼控件就找不到默認UI。
如果控件需要被繼承的話,最好把sealed關鍵字移除。
2.2 Themes/Generic.xaml
<Style TargetType="local:MyFirstControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyFirstControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
XAML負責定義控件的外觀。在第一次創建控件后VisualStudio會自動創建這個文件,並且插入圖中的代碼。注意其中兩個TargetType="local:MyFirstControl",第一個用於匹配MyFirstControl.cs中的DefaultStyleKey,第二個確定ControlTemplete針對的控件類型。兩個都不可以移除。Style的內容是一組Setter的集合,除了Template外,還可以添加其它的Setter指定控件的默認外觀。
2.3 使用MyFirstControl
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<local:MyFirstControl />
</Grid>
</Page>
通常情況下MainPage已經引用了local命名控件,所以只需<local:MyFirstControl />這段xaml即可輕松使用剛剛創建好的控件。
2.4 使用Blend修改DefaultStyle
就算經驗豐富的開發者仍免不了使用Blend這個工具來編輯Style和ControlTemplate,幸好Blend上手十分簡單。
使用Blend打開項目后,在“資源”面板展開Generic.xaml節點,選中MyFirstControl,點擊編輯資源:
在“對象與時間線”面板,選中“Style”節點可在右側“屬性”面板編輯Style中除Template以外的屬性:
在“Style”節點,右鍵打開菜單,選中“編輯模版”->“編輯當前項”開始編輯Template,此時左側“對象與時間線”面板展示Template中的結構:
此后,可在編輯區域的上方選擇編輯Style或者編輯Template:
由於這個主題主要目的是介紹模板化控件,所以不會深入討論Blend的操作。