WPF/Silverlight 中的控件都有Style和Template两种属性。前者解释为样式,是用来改变控件原有属性的,比如 Button 控件的(Width,Height,Background 等等)。后者被解释为模版,用于定义控件的内部结构,可以对控件的外观和形状进行改变,比如可以把Button控件的形状由原来的矩形改变圆形。
WPF/Silverlight控件主要分为以下三类:
Control类型
– Template属性 (ControlTemplate类型)
– ContentPresenter
– ContentTemplate (DataTemplate类型)
ContentControl类型
– Template属性 (ControlTemplate类型) 继承自Control
– ContentTemplate (DataTemplate类型)
ItemsControl类型
– Template属性 (ControlTemplate类型) 继承自Control
– ItemsPanel属性 (ItemsPanelTemplate类型) 指定布局容器
– ItemTemplate属性 (DateTemplate类型) 每个Item的Template
通过上面的Control类型及Template属性,我们可以发现两种最基本Template类型,其实就是ControlTemplate和 DateTemplate。
下面通过实例,对他们进行一一介绍和总结。
1、ControlTemplate:用于描述控件本身的视觉样式和行为,一般用于单一内容控件。
举例:我们修改一个Button的Template:
<Style x:Key="LxButtonA" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="80" Height="40" HorizontalAlignment="Center" VerticalAlignment="Center">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Green" Offset="1"/>
<GradientStop Color="White" Offset="0"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<TextBlock FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" Text="Hello"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
对Button应用该样式:
<Button Style="{StaticResource LxButtonA}" Height="40" Width="80" Content="Silverlight"/>
效果如下图:
这时候,会发现,我们在Xaml中虽然对Button的Content属性赋值为“silverlight” ,但是Button并没有显示,而是显示的Template中TextBlock的Text值Hello,这是因为我们定义的ControlTemplate重写了原来Button中的Content控件,我们可以这样修改:
<Style x:Key="LxButtonB" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" HorizontalAlignment="Center" VerticalAlignment="Center">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Green" Offset="1"/>
<GradientStop Color="White" Offset="0"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--<TextBlock FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Content}"/>-->
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
将原来的模版中的TextBlock控件的Text属性修改为: Text="{TemplateBinding Content}",TemplateBinding 解释为模板绑定扩展是用来把原对象中的属性和模板对象中的属性联系起来
为了提高性能,我们可以用一个ControlPresenter来代替TextBlock,效果一样的。由于篇幅有限,两者的区别本文不做介绍,具体请点击这里查看。
对Button应用该样式:
<Button Style="{StaticResource LxButtonB}" Height="40" Width="80" Content="World"/>
效果如下图:
再来说说ContentTemplate属性,这个属性是ContentControl类的属性,其返回类型是DataTemplate类,它主要用于在不改变控件行为方式的基础上,只对控件的内容进行修改。
<Style x:Key="LxButtonC" TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="Image/1.png" Height="64" Width="64"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
对Button应用该样式,只是对Button的Content进行了更改,其他行为方式都没有变化,效果如下图:
2、DataTemplate:用于描述控件的Content(数据对象)的视觉样式。
我们来用一个ItemsControl来进行举例,用ListBox显示一列图片,首先我们定义一个类DateItem:
public class DataItem
{
/// <summary>
/// 图片路径
/// </summary>
public string ImagePath { get; set; } /// <summary>
/// 显示文字
/// </summary>
public string ShowText { get; set; }
}
定义ListBox的样式模版并应用该样式
<Style x:Key="LxListBoxA" TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/>
<TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox x:Name="MyList" Style="{StaticResource LxListBoxA}"/>
对List进行绑定::
List<DataItem> DataList = new List<DataItem>();
DataList.Add(new DataItem() { ImagePath = @"Image/1.png", ShowText = "人物" });
DataList.Add(new DataItem() { ImagePath = @"Image/2.png", ShowText = "楼房" });
DataList.Add(new DataItem() { ImagePath = @"Image/3.png", ShowText = "电池" });
MyList.ItemsSource = DataList;
效果如下图所示:
对于ItemsControl类型控件,都有ItemsPanel这个属性,其返回值是ItemsPanelTemplate,用来指定控件的子项的布局样式,其他控件比如Combox,TreeView,DataGrid,TabelControl也都均有此属性。
我们可以修改上面ListBox的ItemsPanel属性,将ListBox竖排变更为横排显示:
<Style x:Key="LxListBoxA" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/>
<TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
显示效果如下图:
其实,在ItemsControl类型的控件中,还有个ItemContainerStyle,这又是什么属性呢?其实,他是控件子项的样式,在ListBox里即ListBoxItem的Style属性,比如我们可以在这个属性中统一设置ListBoxItem的字体字号:
<Style x:Key="LxListBoxA" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel>
<Image Source="{Binding ImagePath}" Height="64" Width="64" Margin="0"/>
<TextBlock Text="{Binding ShowText}" HorizontalAlignment="Center" Margin="6" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="FontSize" Value="20"/>
</Style>
</Setter.Value>
</Setter>
</Style>
运行结果如下图:
本篇通过实例对WPF/Silverlight 的ControlTemplate和DataTemplate的使用方式进行了总结,另外还有一种HierarchicalDataTemplate继承与DataTemplate,主要用于对TreeView,Menu等控件的样式绑定,下一篇我们主要介绍利用HierarchicalDataTemplate层级模版数据类型绑定Silverlight中的TreeView.