10-2.WPF的Style

构成Style的最重要两个元素是Setter和Trigger,Setter设置控件的静态外观风格,Trigger设置控件的行为风格。

Setter

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">
<Setter Property="FontSize" Value="24"></Setter>
<Setter Property="TextDecorations" Value="Underline"></Setter>
<Setter Property="FontStyle" Value="Italic"></Setter>
</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>

10-2.WPF的Style_ui

如果想设置控件的ControlTemplate,只需要把Setter的Property设为Template并为Value提供一个ControlTemplate对象即可。

Trigger

当满足某些条件会触发的行为,触发器比较像事件,事件一般由用户触发,而Trigger除了有事件触发的EventTrigger外,还有数据变化触发形的Trigger/DataTrigger以及多条件触发形的MultiTrigger/MultiDataTrigger等。

基本Trigger

类似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">
<Style.Triggers>
<Trigger Property="IsChecked" Value="true">
<Trigger.Setters>
<Setter Property="FontSize" Value="20"/>
<Setter Property="Foreground" Value="Orange"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</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>

10-2.WPF的Style_xml_02

MultiTrigger

多个条件同时成立才会触发,MultiTrigger具有一个Conditions属性,该属性指明要同时成立的条件。

案例:将上面的案例改为需同时满足勾选状态和勾选内容为C时才会触发。

<Style TargetType="CheckBox">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="true"/>
<Condition Property="Content" Value="B"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="FontSize" Value="20"/>
<Setter Property="Foreground" Value="Orange"/>
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>

10-2.WPF的Style_wpf_03

DataTrigger

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">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource cbtr}}" Value="false">
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</DataTrigger>

</Style.Triggers>
</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。

10-2.WPF的Style_wpf_04

MultiDataTrigger

多个数据同时满足时才能触发。

案例:界面上使用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">
<!--使用Style设置Datatemplate-->
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" Width="60"></TextBlock>
<TextBlock Text="{Binding Name}" Width="120"></TextBlock>
<TextBlock Text="{Binding Skill}" Width="60"></TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<!--MultiDataTrigger-->
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=Id}" Value="2"></Condition>
<Condition Binding="{Binding Path=Name}" Value="Darren"></Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Orange"></Setter>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</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;
}

10-2.WPF的Style_wpf_05

EventTrigger

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">
<Style.Triggers>
<!--鼠标进入-->
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Width"></DoubleAnimation>
<DoubleAnimation To="150" Duration="0:0:0.2" Storyboard.TargetProperty="Height"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<!--鼠标离开-->
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Width"></DoubleAnimation>
<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Height"></DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Width="40" Height="40" Content="OK"></Button>
</Grid>
</Window>

10-2.WPF的Style_wpf_06

触发器并非只能用在Style中,各种Template也可以拥有自己的触发器。