WPF的样式类似HTML的CSS,属于资源,可以在设计页面或者资源文件中设计样式,然后在控件上引用样式。
资源对象,不属于样式,定义如下。 不需要用<Style> </Style>括起来。
<Window.Resources> <FontFamily x:Key="ButtonFontFamily">Times New Roman</FontFamily> <sys:Double x:Key="ButtonFontSize">18</sys:Double> <FontWeight x:Key="ButtonFontWeight">Bold</FontWeight> </Window.Resources>
一、样式的两类
普通样式
<Window.Resources> <Style x:Key="BigFontButtonStyle" TargetType="TextBlock"> //这个样式只能用在TextBlock <Setter Property="Control.FontFamily" Value="Times New Roman"/> <Setter Property="Control.FontSize" Value="{DynamicResource ButtonFontSize}"/>//在样式中使用资源对象 <Setter Property="Control.FontWeight" Value="Bold"/> </Style> </Window.Resources>
指定某类控件的样式。如下将设置页面中所有的TextBlock样式。 注意这里的<Style TargetType="TextBlock">中没有基础样式的x:Key="BigFontButtonStyle"
<Window.Resources> <Style TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="TextAlignment" Value="Center"/> <Setter Property="Padding" Value="5"/> </Style> </Window.Resources>
二、样式的继承
可以在资源文件中定义一个基础样式,被其他样式继承(或者叫做扩展)。
<Window.Resources> <Style x:Key="BaseOnStyle" TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Center"/> <Setter Property="TextAlignment" Value="Center"/> <Setter Property="Padding" Value="5"/> </Style> <Style x:Key="TextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseOnStyle}"> <Setter Property="Control.Foreground" Value="Red"/> </Style> </Window.Resources>
三、样式的引用
样式定义好后,可以在控件通过样式名称直接引用。这里区分动态引用和静态引用。动态引用的样式,程序运行后在后台代码再修改样式源文件后,控件会使用修改后的样式,而静态的则不会。
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="人员列表" Style="{DynamicResource TextBlockStyle}" />
在控件中也可以直接使用资源对象
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="人员列表" FontFamily="{DynamicResource ButtonFontFamily}" />
四、样式触发器
WPF样式还支持触发器,在样式中定义的触发器,只有在该属性或事件发生时才会被触发,下面具体看看简单的样式触发器是如何定义和使用的,具体的XAML代码如下所示:
<Window x:Class="StyleDemo.SimpleTriggers" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="SimpleTriggers" Height="300" Width="300"> <Window.Resources> <Style x:Key="BigFontButton"> <Style.Setters> <Setter Property="Control.FontFamily" Value="Times New Roman" /> <Setter Property="Control.FontSize" Value="18" /> </Style.Setters> <!--样式触发器--> <Style.Triggers> <!--获得焦点时触发--> <Trigger Property="Control.IsFocused" Value="True"> <Setter Property="Control.Foreground" Value="Red" /> </Trigger> <!--鼠标移过时触发--> <Trigger Property="Control.IsMouseOver" Value="True"> <Setter Property="Control.Foreground" Value="Yellow" /> <Setter Property="Control.FontWeight" Value="Bold" /> </Trigger> <!--按钮按下时触发--> <Trigger Property="Button.IsPressed" Value="True"> <Setter Property="Control.Foreground" Value="Blue" /> </Trigger> </Style.Triggers> </Style> </Window.Resources> <StackPanel Margin="5"> <Button Padding="5" Margin="5" Style="{StaticResource BigFontButton}" >A Big Button</Button> <TextBlock Margin="5">Normal Content.</TextBlock> <Button Padding="5" Margin="5" >A Normal Button</Button> </StackPanel> </Window>
上面定义的触发器都是在某个属性发生变化时触发的,也可以定义当某个事件激活时的触发器,我们也把这样的触发器称为事件触发器,下面示例定义的事件触发器是等待MouseEnter事件,一旦触发MouseEnter事件,则动态改变按钮的FontSize属性来形成动画效果,具体的XAML代码如下所示:
<Window x:Class="StyleDemo.EventTrigger" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="EventTrigger" Height="300" Width="300"> <Window.Resources> <Style x:Key="BigFontButton"> <Style.Setters> <Setter Property="Control.FontFamily" Value="Times New Roman" /> <Setter Property="Control.FontSize" Value="18" /> <Setter Property="Control.FontWeight" Value="Bold" /> </Style.Setters> <Style.Triggers> <!--定义事件触发器--> <EventTrigger RoutedEvent="Mouse.MouseEnter"> <!--事件触发时只需的操作--> <EventTrigger.Actions> <!--把动画放在动画面板中--> <BeginStoryboard> <!--在0.2秒的时间内将字体放大到22单位--> <Storyboard> <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="FontSize" To="22" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <!--鼠标移开触发的事件--> <EventTrigger RoutedEvent="Mouse.MouseLeave"> <EventTrigger.Actions> <BeginStoryboard> <!--在1秒的时间内将字体尺寸缩小到原来的大小--> <!--如果目标字体尺寸没有明确指定,则WPF将默认使用第一次动画之前按钮的字体尺寸--> <Storyboard> <DoubleAnimation Duration="0:0:1" Storyboard.TargetProperty="FontSize" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style> </Window.Resources> <StackPanel Margin="5"> <Button Padding="5" Margin="5" Style="{StaticResource BigFontButton}" >A Big Button</Button> <TextBlock Margin="5">Normal Content.</TextBlock> <Button Padding="5" Margin="5" >A Normal Button</Button> </StackPanel> </Window>
数据触发器
下面例子中,当TextBox的Text长度小于7个字符时其Border会保持红色。XAML代码如下:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="WPF样式的使用" Height="500" Width="800" WindowStartupLocation="CenterScreen"> <Window.Resources> <local:L2BConverter x:Key="cvtr" /> <Style TargetType="TextBox"> <Style.Triggers> <DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource cvtr}}" Value="false"> <Setter Property="BorderBrush" Value="Red"/> <Setter Property="BorderThickness" Value="1"/> </DataTrigger> </Style.Triggers> </Style> </Window.Resources> <StackPanel> <TextBox Margin="5"/> <TextBox Margin="5,0"/> <TextBox Margin="5"/> </StackPanel> </Window>
这里用到了Converter,我们创建如下的Converter:
using System; using System.Windows.Data; namespace WpfApplication1 { public class L2BConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { int textLength = (int)value; return textLength > 6 ? true : false; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }
事件触发器
EventTrigger是触发器中最特殊的一个。首先,它不是由属性值或数据的变化来触发而是由事件来触发;其次,被触发后它并非应用一组Setter,而是执行一段动画。因此,UI层的动画效果往往与EventTrigger相关联。
在下面这个例子中创建了一个针对Button的Style,这个Style包含两个EventTrigger,一个由MouseEnter事件触发,另一个由MouseLeave事件触发。XAML代码如下:
<Window.Resources> <Style TargetType="Button"> <Style.Triggers> <!--鼠标进入--> <EventTrigger RoutedEvent="MouseEnter"> <BeginStoryboard> <Storyboard> <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Width"/> <DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Height"/> </Storyboard> </BeginStoryboard> </EventTrigger> <!--鼠标离开--> <EventTrigger RoutedEvent="MouseLeave"> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width"/> <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Style.Triggers> </Style> </Window.Resources> <Canvas> <Button Width="40" Height="40" Content="OK"/> </Canvas>