构成Style的最重要两个元素是Setter和Trigger,Setter设置控件的静态外观风格,Trigger设置控件的行为风格。
Property指明为目标的哪个属性赋值,Value则是提供属性值。
<Window x:Class="WpfApplication1.Window40"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window40" Height="310" Width="426">
<Window.Resources>
<Style TargetType="TextBlock">
"FontSize" Value="24">
"TextDecorations" Value="Underline">
"FontStyle" Value="Italic">
Style>
Window.Resources>
<StackPanel Margin="5">
<TextBlock Text="Hello WPF!">TextBlock>
<TextBlock Text="This is a sample for style!">TextBlock>
<TextBlock Text="by Time 2012-11-12!" Style="{x:Null}">TextBlock>
StackPanel>
Window>
如果想设置控件的ControlTemplate,只需要把Setter的Property设为Template并为Value提供一个ControlTemplate对象即可。
当满足某些条件会触发的行为,触发器比较像事件,事件一般由用户触发,而Trigger除了有事件触发的EventTrigger外,还有数据变化触发形的Trigger/DataTrigger以及多条件触发形的MultiTrigger/MultiDataTrigger等。
类似Setter,也有Property和Value两个属性,Property是关注的属性名称,Value是触发条件,Trigger类还有一个Setters属性,这是一组Setter当触发条件,这组Setters就会被应用。
案例:当勾选了目标时,字体和颜色会改变
<Window x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="300">
<Window.Resources>
<Style TargetType="CheckBox">
"IsChecked" Value="true">
"FontSize" Value="20"/>
"Foreground" Value="Orange"/>
Style>
Window.Resources>
<StackPanel>
<CheckBox Content="A" Margin="5"/>
<CheckBox Content="B" Margin="5"/>
<CheckBox Content="C" Margin="5"/>
<CheckBox Content="D" Margin="5"/>
StackPanel>
Window>
多个条件同时成立才会触发,MultiTrigger具有一个Conditions属性,该属性指明要同时成立的条件。
案例:将上面的案例改为需同时满足勾选状态和勾选内容为C时才会触发。
<Style TargetType="CheckBox">
"IsChecked" Value="true"/>
"Content" Value="B"/>
"FontSize" Value="20"/>
"Foreground" Value="Orange"/>
Style>
DataTrigger对象的Binding属性会把数据源送进来,一旦送来的值与Value属性一致,则触发。
案例:TextBox的Text长度小于7,Border保持红色。
<Window x:Class="WpfApplication1.Window42"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window42" Height="184" Width="324">
<Window.Resources>
<local:L2BConverter x:Key="cbtr">local:L2BConverter>
<Style TargetType="TextBox">
"{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource cbtr}}" Value="false">
"BorderBrush" Value="Red">
"BorderThickness" Value="1">
Style>
Window.Resources>
<StackPanel>
<TextBox Margin="5">TextBox>
<TextBox Margin="5,0">TextBox>
<TextBox Margin="5">TextBox>
StackPanel>
Window>
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();
}
}
数据源使用了RelativeSource,如果不明确指出Source的值,Binding会把控件的DataContext属性作为数据源而不是把控件自身作为数据源。我们关注的字符串的长度,如何基于长度进行判断就要使用到了Converter。
多个数据同时满足时才能触发。
案例:界面上使用ListBox显示一列Student数据,当Student对象同时满足Id为2,Name为Darren的时候高亮
<Window x:Class="WpfApplication1.Window43"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window43" Height="262" Width="425">
<Window.Resources>
<Style TargetType="ListBoxItem">
"ContentTemplate" >
"Horizontal" >
"{Binding Id}" Width="60">
"{Binding Name}" Width="120">
"{Binding Skill}" Width="60">
"{Binding Path=Id}" Value="2">
"{Binding Path=Name}" Value="Darren">
"Background" Value="Orange">
Style>
Window.Resources>
<StackPanel>
<ListBox x:Name="lbInfos" Margin="5">ListBox>
StackPanel>
Window>
private void InitialInfo()
{
List<Student38> infos = new List<Student38>() {
new Student38(){ Id=1, Name="Tom", Skill="Java"},
new Student38(){ Id=2, Name="Darren", Skill="WPF"},
new Student38(){ Id=3, Name="Jacky", Skill="Asp.net"},
new Student38(){ Id=2, Name="Andy", Skill="C#"},
};
this.lbInfos.ItemsSource = infos;
}
EventTrigger是最特殊的一个,它不是由属性值或者数据变化来触发,而是由事件来触发。其次,被触发后它并非应用一组Setter,而是执行一段动画,因此UI层的动画往往用EventTrigger来触发。
<Window x:Class="WpfApplication1.Window44"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window44" Height="258" Width="321">
<Window.Resources>
<Style TargetType="Button">
"MouseEnter" >
"150" Duration="0:0:0.2" Storyboard.TargetProperty="Width">
"150" Duration="0:0:0.2" Storyboard.TargetProperty="Height">
"MouseLeave">
"0:0:0.2" Storyboard.TargetProperty="Width">
"0:0:0.2" Storyboard.TargetProperty="Height">
Style>
Window.Resources>
<Grid>
<Button Width="40" Height="40" Content="OK">Button>
Grid>
Window>
触发器并非只能用在Style中,各种Template也可以拥有自己的触发器。