7.模板Template

  • 7.模板Template已关闭评论
  • 123 次浏览
  • A+
所属分类:.NET技术
摘要

WPF的模板基类叫FrameworkTemplate,它是一个抽象类,它有三个子类,分别是ControlTemplate(控件模板)、ItemsPanelTemplate(元素面板模板)和DataTemplate(数据模板)

WPF的模板基类叫FrameworkTemplate,它是一个抽象类,它有三个子类,分别是ControlTemplate(控件模板)、ItemsPanelTemplate(元素面板模板)和DataTemplate(数据模板)

ControlTemplate控件模板用于定义控件的外观,也就是Control基类的Template属性,而绝大多数控件都继承于Control基类,意味着我们都可以去重新定义它们的视觉外观。

DataTemplate数据模板即数据的外衣。用于从一个对象中提取数据,并在内容控件或列表控件的各个项中显示数据。比如ContentControl基类中的ContentTemplate属性,或者集合控件ItemsControl基类ItemTemplate属性,它们都是DataTemplate数据模板,用来定义数据的外观(数据的呈现形式)。

ItemsPanelTemplate元素面板模板也是用于ItemsControl控件或ItemsControl的子类控件中,因为在集合控件中要考虑每个元素之间的布局方式,所以可以采用ItemsPanelTemplate去定义。ItemsControl基类有一个ItemsPanel属性,它就是一个ItemsPanelTemplate模板。

ControlTemplate控件模板

默认情况下,Button按钮的内容只能显示文字,我们可以设置它的Content属性即可。也可以设置它的Width和Height,改变它的尺寸,但是,它始终是一个矩形的按钮。假如我们希望得到一个圆形的按钮、或者带图标的按钮,这个时候就需要去改变按钮的内部结构外观——ControlTemplate控件模板

FrameworkElement基类有一个Template属性就是指控件的ControlTemplate模板,这就意味着,几乎所有的WPF控件都是可以修改它的结构和外观(可视化树)的。注意,不能仅替换控件的可视化树的一部分;若要更改控件的可视化树,必须将该控件的 Template 属性设置为新的完整 ControlTemplate

查看控件的默认模板:点击button-->鼠标单击右键-->编辑模板-->编辑副本,会弹出一个对话框,点击确定。

 <Window.Resources>         <Style x:Key="FocusVisual">             <Setter Property="Control.Template">                 <Setter.Value>                     <ControlTemplate>                         <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>         <SolidColorBrush x:Key="Button.Static.Background" Color="#FFDDDDDD"/>         <SolidColorBrush x:Key="Button.Static.Border" Color="#FF707070"/>         <SolidColorBrush x:Key="Button.MouseOver.Background" Color="#FFBEE6FD"/>         <SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>         <SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>         <SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>         <SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>         <SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>         <SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>         <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">             <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>             <Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>             <Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}"/>             <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>             <Setter Property="BorderThickness" Value="1"/>             <Setter Property="HorizontalContentAlignment" Value="Center"/>             <Setter Property="VerticalContentAlignment" Value="Center"/>             <Setter Property="Padding" Value="1"/>             <Setter Property="Template">                 <Setter.Value>                     <ControlTemplate TargetType="{x:Type Button}">                         <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">                             <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>                         </Border>                         <ControlTemplate.Triggers>                             <Trigger Property="IsDefaulted" Value="true">                                 <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>                             </Trigger>                             <Trigger Property="IsMouseOver" Value="true">                                 <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>                                 <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>                             </Trigger>                             <Trigger Property="IsPressed" Value="true">                                 <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>                                 <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>                             </Trigger>                             <Trigger Property="IsEnabled" Value="false">                                 <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>                                 <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>                                 <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>                             </Trigger>                         </ControlTemplate.Triggers>                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>     </Window.Resources>

我们关注一下Setter项目设置Template属性的写法,因为Template属性是ContorlTemplate类型,所以在上面的代码中实例化了一个ControlTemplate对象,并且,TargetType="{x:Type Button}",表示这个ContorlTemplate实例是给Button定义的模板。

而在ContorlTemplate对象中,定义了一棵可视化树。

这里定义了一个Border装修器,里面有一个ContentPresenter对象。什么是ContentPresenter对象?

ContentPresenter继承于FrameworkElement,说明它也是一个控件。从命名上看,它叫内容主持者,本质上它只是一个占座的,为谁占座?为ContentControl内容控件占座。因为Button继承于ContentControl,所以Button也有Content属性,在ContentTemplate中的ContentPresenter可视为等于Content属性

控件模板的几种设置方式:

1.将ControlTemplate定义在在控件中

<Button Content="将ControlTemplate定义在在控件中"          Width="280" Height="40" Margin="10" Foreground="#747787">     <Button.Template>         <ControlTemplate TargetType="Button">             <Border Background="Transparent" CornerRadius="5" BorderThickness="1" BorderBrush="#C9CCD5">                 <ContentPresenter  HorizontalAlignment="Center" VerticalAlignment="Center"/>             </Border>         </ControlTemplate>     </Button.Template> </Button>

2.将ControlTemplate定义在资源中

<Window.Resources>     <ControlTemplate x:Key="ButtonTemplate" TargetType="Button">         <Border Background="#C6D2FC" CornerRadius="5" BorderThickness="1" BorderBrush="#545BAD">             <ContentPresenter  HorizontalAlignment="Center" VerticalAlignment="Center"/>         </Border>     </ControlTemplate> </Window.Resources>   <Button Content="将ControlTemplate定义在资源中"          Template="{StaticResource ButtonTemplate}"          Width="280" Height="40" Margin="10" Foreground="#707CA5"/>

3.将ControlTemplate定义在Style样式中

<Button Content="将ControlTemplate定义在Style样式中"          Width="280" Height="40" Margin="10" Foreground="White">     <Button.Style>         <Style TargetType="Button">             <Setter Property="Template">                 <Setter.Value>                     <ControlTemplate TargetType="Button">                         <Border Background="#7AAB7D" CornerRadius="5">                             <Grid>                                 <Grid.ColumnDefinitions>                                     <ColumnDefinition Width="auto"/>                                     <ColumnDefinition/>                                 </Grid.ColumnDefinitions>                                 <TextBlock Grid.Column="0" Text=""                                             VerticalAlignment="Center"                                             Margin="3" FontSize="18"/>                                 <ContentPresenter Grid.Column="1"                                                    HorizontalAlignment="Center"                                                    VerticalAlignment="Center"/>                             </Grid>                         </Border>                     </ControlTemplate>                 </Setter.Value>             </Setter>         </Style>     </Button.Style> </Button>

 

DataTemplate数据模板

DataTemplate 继承于FrameworkTemplate基类,它有3个属性,分别是DataType 、Triggers 和DataTemplateKey 。DataType表示当前数据模板所针对的数据类型,Triggers 是触发器集合。

在ItemsControl集合控件中就有一个ItemTemplate属性,它的类型就是DataTemplate 。说明所有继承于ItemsControl的集合子控件都可以设置数据模板。

案列:

<Grid>     <ScrollViewer>         <ItemsControl ItemsSource="{Binding Persons}"><!--数据控件-->             <ItemsControl.ItemTemplate><!--ItemTemplate属性-->                 <DataTemplate><!--数据模板-->                     <Border x:Name="border"                         Width="280"                         Height="200"                         Margin="5"                         BorderThickness="1"                          BorderBrush="Gray">                         <Grid>                             <Grid.RowDefinitions>                                 <RowDefinition/>                                 <RowDefinition/>                             </Grid.RowDefinitions>                             <StackPanel Grid.Row="0" Margin="20">                                 <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="20"/>                                 <Rectangle Height="5"/>                                 <TextBlock Text="{Binding Occupation}" FontSize="16"/>                             </StackPanel>                             <StackPanel Grid.Row="1" Orientation="Horizontal">                                 <TextBlock Grid.Column="0" Text=""                                              VerticalAlignment="Center"  Margin="20"                                             FontSize="50" Foreground="#E26441"/>                                 <StackPanel Margin="30 0 0 0" Width="150">                                     <TextBlock Text="COMPANY NAME"/>                                     <TextBlock Text="Age:">                                         <Run Text="{Binding Age}"/>                                     </TextBlock>                                     <TextBlock Text="Money:">                                         <Run Text="{Binding Money, StringFormat={}{0:C}}"/>                                     </TextBlock>                                     <TextBlock Text="Address:" TextWrapping="Wrap">                                         <Run Text="{Binding Address}"/>                                     </TextBlock>                                 </StackPanel>                             </StackPanel>                         </Grid>                     </Border>                     <DataTemplate.Triggers>                         <Trigger Property="IsMouseOver" Value="True">                             <Setter Property="Background" Value="#7AAB7D" TargetName="border" />                         </Trigger>                     </DataTemplate.Triggers>                 </DataTemplate>             </ItemsControl.ItemTemplate>         </ItemsControl>     </ScrollViewer>     </Grid>

 

ItemsPanelTemplate布局模板

ItemsPanelTemplate用于指定集合控件中元素与元素之间的布局的方式,所以,ItemsPanelTemplate其实就是一个布局面板,而我们在前面的章节中已经学习了WPF的面板控件,它们都继承于Panel基类,分别是Grid、UniformGrid、StackPanel、WrapPanel、DockPanel、Canvas等。而在使用ItemsPanelTemplate模板去设置某一个集合控件的元素布局面板时,默认使用StackPanel布局,或者WrapPanel。

例如在上的ItemsControl控件中,我们有4个元素,它们都是垂直排列的。我们可以修改ItemsPanel属性,用以设置元素以瀑布流的方式排列显示。

<ItemsControl.ItemsPanel>     <ItemsPanelTemplate>         <WrapPanel/>     </ItemsPanelTemplate> </ItemsControl.ItemsPanel>

此时ItemsControl中的元素便随着Window窗体大小的改变,而自适应水平排列其中的元素

<ListBox ItemsSource="{Binding Persons}" >     <ItemsControl.ItemsPanel>         <ItemsPanelTemplate>             <WrapPanel/>         </ItemsPanelTemplate>     </ItemsControl.ItemsPanel>     <ItemsControl.ItemTemplate>         <DataTemplate>             <Border x:Name="border"                     Width="280"                     Height="200"                     Margin="5"                     BorderThickness="1"                      BorderBrush="Gray">                 <Grid>                     <Grid.RowDefinitions>                         <RowDefinition/>                         <RowDefinition/>                     </Grid.RowDefinitions>                     <StackPanel Grid.Row="0" Margin="20">                         <TextBlock Text="{Binding Name}" FontWeight="Bold" FontSize="20"/>                         <Rectangle Height="5"/>                         <TextBlock Text="{Binding Occupation}" FontSize="16"/>                     </StackPanel>                     <StackPanel Grid.Row="1" Orientation="Horizontal">                         <TextBlock Grid.Column="0" Text=""                                          VerticalAlignment="Center"  Margin="20"                                         FontSize="50" Foreground="#E26441"/>                         <StackPanel Margin="30 0 0 0" Width="150">                             <TextBlock Text="COMPANY NAME"/>                             <TextBlock Text="Age:">                                     <Run Text="{Binding Age}"/>                             </TextBlock>                             <TextBlock Text="Money:">                                     <Run Text="{Binding Money, StringFormat={}{0:C}}"/>                             </TextBlock>                             <TextBlock Text="Address:" TextWrapping="Wrap">                                     <Run Text="{Binding Address}"/>                             </TextBlock>                         </StackPanel>                     </StackPanel>                 </Grid>             </Border>             <DataTemplate.Triggers>                 <Trigger Property="IsMouseOver" Value="True">                     <Setter Property="Background" Value="#7AAB7D" TargetName="border" />                 </Trigger>             </DataTemplate.Triggers>         </DataTemplate>     </ItemsControl.ItemTemplate> </ListBox>