上一篇關於模板的文章:
《深入淺出WPF》—— Data / Control 模板的使用(一)
爲 Template 設置其應用目標有兩種方法:
- 一種是逐個設置控件的 Template / ContentTemplate 等屬性,不想應用則不設置(上一文用)
- 一種是
整體應用
,即把 Template應用在某個控件或數據上
文章目錄
ControlTemplate的應用
把 ControlTemplate 應用在所有目標上需要藉助 Style 來實現,但 Style 不能標記 x:Key
例如下面的代碼:
<Window x:Class="WpfApp31.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="230">
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
// *************************************** //
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" CornerRadius="20" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
// *************************************** //
<Setter Property="Margin" Value="5"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Background" Value="LightBlue"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBox/>
<TextBox/>
<TextBox Style="{x:Null}" Background="Black"/>
</StackPanel>
</Window>
(注
:核心部分我已經用 // *** // 標記 . . .)
我們發現,控件模塊就是修改了一些風格而已,並且作用於指定的類型
Style 沒有 x:Key標記,默認爲應用到所有由 x:Type指定的控件上,如果不需要則把 Style設置 {x:null}。
效果如下:
其中,前兩個 TextBox爲默認風格,第三個 Style爲 null . . .
DataTemplate的應用
把 DataTemplate 應用在某個數據類型上的方法是設置 DataTemplate 的 Data屬性,並且把 DataTemplate 作爲資源時也不能帶有 x:Key標記。
很多時候數據是以 XML形式存儲的,因爲這樣做很方便。DataTemplate 很智能,具有直接把 XML數據結點當作目標對象的功能 ——
XML 數據中的元素名(標籤名)可以作爲 DataType
,元素的子結點 和 Attribute 可以使用 XPath來訪問。
我們需要完成上一文中類似的數據柱形圖:參考開頭的鏈接
下面的代碼使用 XmlDataProvider 作爲數據源(XPath 必需指出一組結點:Units/Unit ):
<Window x:Class="WpfApp33.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataTemplate" SizeToContent="WidthAndHeight">
<Window.Resources>
// *************************************************//
<DataTemplate DataType="Unit">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid>
<Rectangle Stroke="Yellow" Fill="Orange"
Width="{Binding XPath=@Price}"/>
<TextBlock Text="{Binding XPath=@Year}"/>
</Grid>
<TextBlock Text="{Binding XPath=@Price}" Margin="5,0"/>
</StackPanel>
</Grid>
</DataTemplate>
// *************************************************//
<XmlDataProvider x:Key="ds" XPath="Units/Unit">
<x:XData>
<Units xmlns="">
<Unit Year ="2001" Price="100"/>
<Unit Year ="2002" Price="120"/>
<Unit Year ="2003" Price="140"/>
<Unit Year ="2004" Price="150"/>
<Unit Year ="2005" Price="130"/>
<Unit Year ="2006" Price="160"/>
</Units>
</x:XData>
</XmlDataProvider>
// *************************************************//
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{Binding Source={StaticResource ds}}"/>
<ComboBox ItemsSource="{Binding Source={StaticResource ds}}" Margin="5"/>
</StackPanel>
</Window>
代碼分爲三部分:
- 定義DataTemplate,指定 DataType, —
@表示引入xml結點的特性 . . .
- XmlDataProvider,提供數據
- 引用數據,數據被默認添加模板
結果圖如下:
HierarchicalDataTemplate的應用
XML最大的優勢是可以方便地表示帶有層級的數據
,比如:
- 年級 --> 班級 --> 小組
- 主菜單 --> 次級菜單 --> 三級菜單
同時,WPF準備了 TreeView
和 MenuItem
控件用來顯示 層級數據
。能夠幫助層級控件顯示層級數據的模板是 HierarchicalDataTemplate
。
下面我們將舉兩個例子來測試一下它們 . . .
TreeView使用
使用 TreeView顯示多層級、不同類型數據。因爲數據類型不同,所以我們需要爲每種數據設計一個模板,這就可以將每種數據類型表示獨有的外觀。
爲了方便,我們將數據直接向上面一樣,定義在XAML代碼中,日常項目中,我們可以寫在單獨的 xml文件中. . .
<Window x:Class="WpfApp34.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataTemplate" SizeToContent="WidthAndHeight">
<Window.Resources>
//********************************************//
<XmlDataProvider x:Key="ds" XPath="Data/Grade">
<x:XData>
<Data xmlns="">
<Grade Name ="一年級">
<Class Name="甲班">
<Group Name="A 組"/>
<Group Name="B 組"/>
<Group Name="C 組"/>
</Class>
<Class Name="乙班">
<Group Name="A 組"/>
<Group Name="B 組"/>
<Group Name="C 組"/>
</Class>
</Grade>
<Grade Name ="二年級">
<Class Name="甲班">
<Group Name="A 組"/>
<Group Name="B 組"/>
<Group Name="C 組"/>
</Class>
<Class Name="乙班">
<Group Name="A 組"/>
<Group Name="B 組"/>
<Group Name="C 組"/>
</Class>
</Grade>
</Data>
</x:XData>
</XmlDataProvider>
//********************************************//
<HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">
<TextBlock Text="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
<RadioButton Content="{Binding XPath=@Name}" GroupName="gn"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding XPath=Student}">
<CheckBox Content="{Binding XPath=@Name}"/>
</HierarchicalDataTemplate>
//********************************************//
</Window.Resources>
<Grid>
<TreeView Margin="5" ItemsSource="{Binding Source={StaticResource ds}}"/>
</Grid>
</Window>
代碼分爲三部分:
- 使用 XmlDataProvider 定義樹形數據,年級 --> 班級 --> 小組
- 使用層級模板 HierarchicalDataTemplate,表示顯示的數據模樣
- 使用 TreeView 調用資源數據
效果如下:
MenuItem使用
下面的例子是同一種數據類型的嵌套結構,我們只需要設計一個 HierarchicalDataTemplate 就可以了,它會產生自動迭代應用的效果。
像上面一樣,數據仍然放在 XAML中,代碼如下:
<Window x:Class="WpfApp35.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="HierarchicalDataTemplate " Height="300" Width="300">
<Window.Resources>
<XmlDataProvider x:Key="ds" XPath="Data/Operation">
<x:XData>
<Data xmlns="">
<Operation Name="文件" Gesture="F">
<Operation Name="新建" Gesture="N">
<Operation Name="項目" Gesture ="Control + P"/>
<Operation Name="網站" Gesture ="Control + W"/>
<Operation Name="文檔" Gesture ="Control + D"/>
</Operation>
<Operation Name="保存" Gesture="S"/>
<Operation Name="剪切" Gesture="P"/>
<Operation Name="退出" Gesture="X"/>
</Operation>
<Operation Name="編輯" Gesture="E">
<Operation Name="拷貝" Gesture ="Control + C"/>
<Operation Name="剪切" Gesture ="Control + X"/>
<Operation Name="粘貼" Gesture ="Control + V"/>
</Operation>
</Data>
</x:XData>
</XmlDataProvider>
<HierarchicalDataTemplate DataType="Operation"
ItemsSource="{Binding XPath=Operation}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
<TextBlock Text="{Binding XPath=@Gesture}"/>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel
<Menu x:Name="m" ItemsSource="{Binding Source={StaticResource ds}}"/>
</StackPanel>
</Window>
和上面的 TreeView一樣,都是先定義數據,然後使用層級模板修飾數據,最後引用數據 . . .