在實(shí)際應用中,ControlTemplate是一個(gè)非常重要的功能。它幫助我們快速實(shí)現很Cool的自定義控件。下面我以Windows Vista SDK中的例子ControlTemplateExamples為基礎,簡(jiǎn)單地分析ControlTemplate的使用。這個(gè)例子工程非常豐富,幾乎包含了所有的標準控件。所以,在實(shí)現自定義控件時(shí),可以先參考這樣進(jìn)行適當的學(xué)習研究。
首先是App.xaml文件,這里它把Application.StartupUri屬性設置為Window1.xaml。然后把工程目錄Resource下所有的控件xaml文件都合成為了應用程序范圍內的資源。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\Shared.xaml" />
<!-- 這里省略 -->
<ResourceDictionary Source="Resources\NavigationWindow.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
這樣的用法很有借鑒意義。在WPF中實(shí)現Skin框架也隨之變得非常簡(jiǎn)單。值需要動(dòng)態(tài)使用不同的XAML文件即可。然后是Window1.xaml文件。它里面幾乎把所有的控件都顯示了一遍。沒(méi)有什么多說(shuō)的。重點(diǎn)看Resource目錄下的自定義控件文件。這里的控件太多,不可能每個(gè)都說(shuō)說(shuō)。我只挑選其中的Button.xaml為例:
<ResourceDictionary <ResourceDictionary.MergedDictionaries> <!-- Focus Visual --> <Style x:Key="ButtonFocusVisual"> 因為這個(gè)XAML文件作為資源使用,所以其根元素是ResourceDictionary,而不再是Window/Application等等。同時(shí),資源文件也可以相互的嵌套,比如上面的包含的Shared.xaml文件。然后定義了一個(gè)Style,注意這里的目標類(lèi)型為Control.Template,也就是針對所有的控件模板有效,所以Style添加了一個(gè)x:Key屬性。這樣就阻止Style適用于當前的所有控件。我們必須顯式的引用這個(gè)Style。相關(guān)內容,可以參考我前面的Style文章。 另一個(gè)需要說(shuō)明的是<ControlTemplate>的子元素,可以是任何的VisualTree。比如這里的Border,也可以是Grid等等。好了,現在定義了一個(gè)名為ButtonFocusVisual的模板,下面只需要引用它即可。 <Style TargetType="Button"> <Border x:Name="Border" ......./> <ControlTemplate.Triggers> </ControlTemplate> 這是真正影響控件外觀(guān)的代碼。因為在定義Style的時(shí)候沒(méi)有指定具體的x:Key,所以將影響所有的Button。如你所見(jiàn),在FocusVisualStyle這個(gè)屬性(類(lèi)型是Style)上我們用資源方式引用了前面定義的命名Style:ButtonFocusVisual。接下來(lái)是定義Template,并為其子元素Border定義了一個(gè)名稱(chēng)。然后就是ControlTemplate的觸發(fā)器。在IsKeyboardFocused屬性滿(mǎn)足條件的情況下,我們把Border(注意這個(gè)Border不是類(lèi)型,而是具體的某個(gè)對象)的BorderBrush修改為另一個(gè)靜態(tài)資源。結合前面的Post,理解也就不難了。 最后,我們還會(huì )發(fā)現一個(gè)有趣的問(wèn)題:這個(gè)例子雖然是ControlTempalte,但工程名稱(chēng)卻是SimpleStyle,從這一點(diǎn)我們也可以看出:Style和Template通常是配合使用才能真正的實(shí)現豐富的自定義功能。
xmlns=" xmlns:x="
<ResourceDictionary Source="Shared.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Margin="5" StrokeThickness="3"
Stroke="#60000000" StrokeDashArray="4 2"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--...............-->
</ResourceDictionary>
<!--.............-->
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<!--.............-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DefaultedBorderBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</Setter.Value>
</Setter>
</Style>
聯(lián)系客服