WPF中每个控件都被设计为无外观的,这意味着我们可以通过一定的方式,完全重定义其可视化外观,而WPF也提供了这种改变外观的方式之一,我们称为模板。wpf的模板有多种方式,可以分为控件模板(ControlTemplate),控件列表模板(ItemsPanelTemplate)和数据模板(DataTemplate)。其中ControlTemplate和ItemsPanelTemplate都属于控件模板,但又有不同的表示。
1、控件模板(ControlTemplate)
理解控件模板,首先得理解两个概念逻辑树和可视化树,逻辑树是我们最基本的要素列表,可视化树是逻辑书的扩展版本,它将元素分为更小的部分。换句话说说,逻辑树仅仅关心到控件级别,而可视化树关心到控件的组成的最基本图形元素。
1.1 定义模板样式
每个控件都有一个内置的方法,用于确定如何渲染控件,该方法称为控件模板,可以使用XAML标记块定义,下面我们定义一个普通的按钮的模板:
<Button x:Name="btn1" Click="Button_Click" > <Button.Template > <ControlTemplate > <Grid > <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/> <TextBlock Name="txtBlock" Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid > </ControlTemplate > </Button.Template> </Button>
效果如下:
模板是控件的Template 属性,Template 是一个ControlTemplate对象,我们可以重定义这个对象,就是重新定义了按钮的界面,ControlTemplate里面可以使用任何控件,比如以下代码:
<Button x:Name="btn1" Click="Button_Click" > <Button.Template > <ControlTemplate > <Grid > <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/> <TextBlock Name="txtBlock" Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" /> <CheckBox IsChecked="True"></CheckBox> </Grid > </ControlTemplate > </Button.Template> </Button>
其效果如下:
不过这种做法不常见,使用的时候需要谨慎处理。
1.2 模板触发器
触器是模板里面一个常用的功能,能为当前控件提供显示的多样性和多状态提供的触发机制,比如按钮,鼠标移上和鼠标移开,获取焦点和非焦点,都不一样,这些在不同状态下的显示,就需要触发器完成,触发器的详细讲解,请查看http://www.cnblogs.com/minhost/p/7464148.html。控件模板触发器,基本能触发常规的触发器,属性和事件等。我们看看触发器如何使用:
<Button x:Name="btn1" Click="Button_Click" > <Button.Template > <ControlTemplate > <Grid > <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/> <TextBlock Name="txtBlock" Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid > <ControlTemplate.Triggers > <Trigger Property="Button.IsMouseOver" Value="True"> <Setter Property="Button.Background" Value="blue"/> </Trigger > </ControlTemplate.Triggers > </ControlTemplate > </Button.Template> </Button>
以上触发器,就是当前鼠标经过的时候,让按钮的背景变为蓝色,可以看到效果如下:
1.3 模板的复用
我们上面的案例,只是把模板放在按钮内部,那么只有这个按钮才能使用,为了实现共享模板等,我们可以把模板定义在resource里面,所以我们完全可以把以上代码添加到window.resource中,如以下代码:
<Window.Resources> <ControlTemplate x:Key="btntemp"> <Grid > <Ellipse Name="faceEllipse" Height="50" Width="100" Fill="{TemplateBinding Button.Background}"/> <TextBlock Name="txtBlock" Text="text" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid > <ControlTemplate.Triggers > <Trigger Property="Button.IsMouseOver" Value="True"> <Setter Property="Button.Background" Value="blue"/> </Trigger > </ControlTemplate.Triggers > </ControlTemplate > </Window.Resources> <Canvas> <Button x:Name="btn1" Click="Button_Click" Template="{StaticResource btntemp}"></Button> </Canvas>
能实现以上相同功能,假如有多个按钮的话,则可以对模板进行复用,如果我们想当前窗体所有的按钮都统一样式,则可以指定 <ControlTemplate x:Key="btntemp" TargetType="Button">,那么界面上所有的按钮(除非特别指定)都会使用当前样式。