使用WPF的過程中,設計界面常會用到幾種模板,如ControlTemplate, ItemsPanelTemplate 和 DataTemplate, 在這里對每一個介紹一番。
ControlTemplate
說明:用以控件控件的外觀,如下代碼就是用來設計一個自定義的按鈕樣式。
<Style TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border BorderThickness="1" BorderBrush="Red" CornerRadius="5"> 1<!--<ContentControl VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>--> 2<!--<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>--> 3<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>


注意點:
示例代碼中1,2,3片段用那一個都是可以的,相同的結果,其中2,3是等價的,使用ContentPresenter時會隱式的進行TemplateBinding,這的確是經常需要的。其中1最終也是使用了ContentPresenter用來呈現內容,所以不建議使用ContentControl,有點大才小用的趕腳。實際上也是如此,ContentControl中包含ContentPresenter.
ItemsPanelTemplate
說明:用以定義集合控件的容器外觀,如ListBox,Combox 等等,這里使用一個自定義的listBox用以說明,其默認外觀是上下排列,這里修改成橫向排列。
示例代碼:
<ListBox HorizontalAlignment="Left" Height="100" Margin="49,111,0,0" VerticalAlignment="Top" Width="100"> <system:String>abc</system:String> <system:String>def</system:String> <system:String>hij</system:String> </ListBox> <ListBox HorizontalAlignment="Left" Height="31" Margin="184,111,0,0" VerticalAlignment="Top" Width="100"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"></StackPanel> </ItemsPanelTemplate> </ListBox.ItemsPanel> <system:String>abc</system:String> <system:String>def</system:String> <system:String>hij</system:String> </ListBox>


DataTemplate
說明:以命名來看,是用來表現數據外觀的,先上一個簡單的示例:
public class Person { public string Name { get; set; } public string Des { get; set; } } <wpfApplication1:Person x:Key="p1" Name="P1" Des="Girl"/> <DataTemplate x:Key="dt1" DataType="wpfApplication1:Person"> <TextBlock> <Run Text="{Binding Name}"/> <Run Text=":"/> <Run Text="{Binding Des}"/> </TextBlock> </DataTemplate> <Button Content="{StaticResource p1}" HorizontalAlignment="Left" Margin="204,219,0,0" VerticalAlignment="Top" Width="193" Height="36"/> <Button Content="{StaticResource p1}" ContentTemplate="{StaticResource dt1}" HorizontalAlignment="Left" Margin="204,275,0,0" VerticalAlignment="Top" Width="193" Height="35"/>
運行結果:


解析:數據模板用來呈現數據,在這個例子中,直接將Button的內容指向一個Person類,若不指定其DataTemplate,則Button的內容只會簡單的顯示為綁定對象的ToString內容,指定了Person的顯示方式,則會按照預期的想法進行呈現。
HierarchicalDataTemplate
該數據模板主要應用於比較復雜的樹形結構中,HierarchicalDataTemplate從DataTemplate繼承而來,其用法也相當的簡單,這里給一個簡單的示例即可。
代碼:
<DockPanel.Resources> <HierarchicalDataTemplate DataType = "{x :Type local :Person}" ItemsSource = "{Binding Path=Persons}"> <TextBlock Text ="{Binding Path =Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType = "{x :Type local :Child}" ItemsSource = "{Binding Path=Persons}"> <TextBlock Text ="{Binding Path =Des}"/> </HierarchicalDataTemplate> </DockPanel.Resources> <TreeView x :Name="st"> </TreeView> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Loaded += MainWindow_Loaded; } private void MainWindow_Loaded( object sender, RoutedEventArgs e) { st.ItemsSource = new List< Person>(){ Person.GetRandomPerson(),Person .GetRandomPerson() }; } } public class Person { public string Name { get; set; } public string Des { get; set; } public List< Child> Persons { get; set; } public static Person GetRandomPerson( int count=0) { var random = new Random( DateTime.Now.Millisecond); var next = random.Next(); var person = new Person {Name = "name" + next, Des = "des" + next}; person.Persons = new List< Child>(); if (count++ < 5) { for ( int i = 0; i < next % 10; i++) { person.Persons.Add( Child.GetRandomPerson(count)); } } return person; } } public class Child { public string Name { get; set; } public string Des { get; set; } public List< Child> Persons { get; set; } public static Child GetRandomPerson( int count = 0) { var random = new Random( DateTime.Now.Millisecond); var next = random.Next(); var person = new Child { Name = "name" + next, Des = "des" + next }; person.Persons = new List< Child>(); if (count++ < 2) { for ( int i = 0; i < next % 10; i++) { person.Persons.Add(GetRandomPerson(count)); } } return person; } }
運行結果:


StyleSelector and DataTemplateSelector
考慮到這樣一種場景,集合控件需要根據不同的行去設置不同的行樣式及內容呈現方式,這就用到了這兩個Selector,需要繼承這兩個類,定義自己需要的效果。同樣的,以代碼作為示例,並演示相關結果
Code:
class MyStyleSelector : StyleSelector { public Style StyleContainsO { get; set; } public Style StyleOther { get; set; } public override Style SelectStyle( object item, DependencyObject container) { Style re; ItemsControl itmesControl = ItemsControl.ItemsControlFromItemContainer(container); var index = itmesControl.ItemContainerGenerator.IndexFromContainer(container); if (index%3==0) re = StyleContainsO; else { re = StyleOther; } return re; } } class MyDataTemplateSelector : DataTemplateSelector { public DataTemplate DataContainsO { get ; set ; } public DataTemplate DataOther { get ; set ; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { if (item.ToString().Contains( "O")) return DataContainsO; return DataOther; } } <Window.Resources > <!-- 數據 --> <x: Array xmlns: sys="clr-namespace:System;assembly=mscorlib" Type="sys:String" x:Key ="array"> <sys: String>Op</sys :String> <sys: String>Kip</sys :String> <sys: String>Opp</sys :String> <sys: String>Oms</sys :String> <sys: String>Kmp</sys :String> </x: Array> <!-- 自定義3種樣式 --> <Style x :Key="st1" TargetType="ListBoxItem"> <Setter Property ="Background" Value="Gray" /> <Setter Property ="HorizontalContentAlignment" Value="Center" /> </Style> <Style x :Key="st2" TargetType="ListBoxItem"> <Setter Property ="Background" Value="DarkOliveGreen" /> <Setter Property ="HorizontalContentAlignment" Value="Center" /> </Style> <DataTemplate x :Key="d1"> <TextBlock Text ="{Binding Mode =OneWay}"></TextBlock> </DataTemplate> <DataTemplate x :Key="d2"> <TextBox Text ="{Binding Mode =OneWay}"></TextBox> </DataTemplate> <!-- XML命名空間loc是MyStyleSelector的CLR命名空間 --> <local: MyStyleSelector x:Key ="mySelector" StyleContainsO="{StaticResource st1}" StyleOther="{StaticResource st2}"/> <local: MyDataTemplateSelector x:Key ="myDataSelector" DataContainsO="{StaticResource d1}" DataOther="{StaticResource d2}"/> </Window.Resources > <ListBox ItemsSource="{StaticResource array}" ItemContainerStyleSelector="{ StaticResource mySelector}" ItemTemplateSelector="{ StaticResource myDataSelector}"> </ListBox >
運行結果:


最后,文章寫的比較亂,也可以說不算是文章,代碼比較多,如果對您有所幫助,那本人也很欣慰,新手上路,歡迎各位吐槽~~