转载于:https://www.cnblogs.com/huangxincheng/category/388852.html
这个楼主写的很详解,也比较基础,刚学wpf的朋友看看很有帮助。
说起样式,大家第一反应肯定是css,好的,先上一段代码。
html{border:0;} ul,form{margin:0; padding:0} body,div,th,td,li,dd,span,p,a{font-size:12px; font-family:Verdana,Arial,"宋体";color:#575757;} h3,input{font-size:12px; font-family:Verdana,Arial,"宋体";color:#4465a2;} body { /*background-color:#eaeaea;*/ /*e5e5e5*/ /*BACKGROUND: url(../images/header_bg.jpg) #fff repeat-x;*/ BACKGROUND: url(../images/color_1.png) #fff repeat-x 0px -233px; margin:0px; padding:0px; } ul{list-style:none;} h1,h2,h4,h5,h6{ font-size:14px; color:#333;} img{border:0;} a {color:#333333;text-decoration:none;} a:hover{color:#ff0000;text-decoration:underline;}
我们知道css实现了内容与样式的分离,既然wpf跟webform非常类似,那么肯定也有一套能够实现css的功能,是的。这就是wpf的style。
一:Style类
首先我们看看Style里面有哪些东西,在vs里面我们可以通过按F12查看类的定义。
下面我们一一解读下:
1:Setters
从上图我们知道Setters的类型是SetterBaseCollection,可以看得出是一个存放SetterBase的集合,SetterBase派生出了两个类
Setter和EventSetter,下面我们看看Setter类的定义。
这里我们看到了两个非常重要KV属性Property和Value,我们拿css找找对应关系。
html{border:0;}
html => Style.TargetType
border => Property
0 => Value
估计大家想迫不及待的试一试,好了,我先做一个简单的demo。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Pink"/>
<Setter Property="FontSize" Value="22"/>
</Style>
</Window.Resources>
<Grid>
<Button Content="一线码农"/>
</Grid>
</Window>
仔细看看,是不是找到了css的感觉,有人肯定要问,这不就是标签选择器吗?能不能做成“id选择器”,当然可以,我们只需要给style取一个名字,
然后在控件上引用一下就ok了。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="mystyle" TargetType="Button">
<Setter Property="Background" Value="Pink"/>
<Setter Property="FontSize" Value="22"/>
</Style>
</Window.Resources>
<Grid>
<Button Style="{StaticResource ResourceKey=mystyle}" Content="一线码农"/>
</Grid>
</Window>
现在我们添加一个label,如果我们也需要同样的“背景色”和“字体”,那么我们是否要重新写一个label的样式吗?答案肯定是否定的,聪明的你肯定会
想到”基类“。我们发现label和button都是继承自ContentControl,都属于内容控件,那么何不在TargetType中定义为ContentControl不就ok了吗?
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <Style x:Key="mystyle" TargetType="ContentControl"> <Setter Property="Background" Value="Pink"/> <Setter Property="FontSize" Value="22"/> </Style> </Window.Resources> <Grid> <Button Style="{StaticResource ResourceKey=mystyle}" Content="Button" Height="23" Margin="132,99,0,0" Name="button1" Width="75" /> <Label Style="{StaticResource ResourceKey=mystyle}" Content="Label" Height="28" Margin="140,168,0,0" Name="label1" /> </Grid> </Window>
2:TargetType
我们在说Setter的时候也提到了,其实TargetType也就是将样式施加到某一个对象上,具体的也没什么好说的。
3:BaseOn
我们知道css具有“继承和覆盖”的特性,同样我们的wpf中也是具有的。
<1>:继承
1 <Window x:Class="WpfApplication1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:sys="clr-namespace:System;assembly=mscorlib" 5 Title="MainWindow" Height="350" Width="525"> 6 <Window.Resources> 7 <Style x:Key="baseStyle" TargetType="Button"> 8 <Setter Property="FontSize" Value="22"/> 9 </Style> 10 <Style x:Key="childStyle" TargetType="Button" 11 BasedOn="{StaticResource ResourceKey=baseStyle}"> 12 <Setter Property="Background" Value="Pink"/> 13 </Style> 14 </Window.Resources> 15 <Grid> 16 <Button Style="{StaticResource ResourceKey=childStyle}" Content="一线码农"/> 17 </Grid> 18 </Window>
从上例中,我们看到childStyle继承到了baseStyle中的fontSize,最终的效果也是我们期望看到的。
<2>:覆盖
我们知道css遵循“就近原则”。
①:“行内”覆盖“嵌入”,“嵌入”覆盖“外部”
我们可以清楚的看到,行内样式覆盖了嵌入样式。
②:同级别遵循“就近”。
从button的颜色上看,我们可以获知Pink已经被BurlyWood覆盖。
4:Triggers
顾名思义,是触发器的意思,我们可以认为是wpf在style中注入了一些很简单,很sb的js代码。
wpf中有5种trigger,都是继承自TriggerBase类。
<1> Trigger,MuliTrigger
我们知道js是事件驱动机制的,比如触发mouseover,mouseout,click等事件来满足我们要处理的逻辑,那么wpf在不用写C#代码的情况下
用trigger就能够简单的满足这些事件处理。
下面举个例子
1 <Window x:Class="WpfApplication1.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:sys="clr-namespace:System;assembly=mscorlib"
5 Title="MainWindow" Height="350" Width="525">
6 <Window.Resources>
7 <Style x:Key="childStyle" TargetType="Button">
8 <Setter Property="Background" Value="BurlyWood"/>
9 <Style.Triggers>
10 <!-- 当IsMouseOver的时候,Button颜色变成粉色 -->
11 <Trigger Property="IsMouseOver" Value="True">
12 <Setter Property="Background" Value="Pink"/>
13 </Trigger>
14 </Style.Triggers>
15 </Style>
16 </Window.Resources>
17 <Grid>
18 <Button Style="{StaticResource ResourceKey=childStyle}" Content="一线码农">
19 </Button>
20 </Grid>
21 </Window>
最后的效果就是当isMouseOver=true的情况下,button的Background变成Pink。
然而trigger只能满足在单一的条件下触发,那么我想在多个条件同时满足的情况下才能触发有没有办法做到呢?刚好MuliTrigger就可以帮你实现。
1 <Window x:Class="WpfApplication1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:sys="clr-namespace:System;assembly=mscorlib" 5 Title="MainWindow" Height="350" Width="525"> 6 <Window.Resources> 7 <Style x:Key="childStyle" TargetType="Button"> 8 <Setter Property="Background" Value="BurlyWood"/> 9 <Style.Triggers> 10 <MultiTrigger> 11 <MultiTrigger.Conditions> 12 <Condition Property="IsMouseOver" Value="True"></Condition> 13 <Condition Property="IsPressed" Value="True"></Condition> 14 </MultiTrigger.Conditions> 15 <Setter Property="Background" Value="Pink"/> 上面两个条件都成立时,才会触发这个设置 16 </MultiTrigger> 17 </Style.Triggers> 18 </Style> 19 </Window.Resources> 20 <Grid> 21 <Button Style="{StaticResource ResourceKey=childStyle}" Content="一线码农"> 22 </Button> 23 </Grid> 24 </Window>
这里我们看到,只有满足了IsMouseOver和IsPressed的时候,我们的button才会变成粉色。
<2>DataTrigger,MultiDataTrigger
这个跟上面的Trigger有什么不同呢?其实也就是DataTrigger多了一个Binding的属性,当然它的实际应用也是最广泛的。
1 <Window x:Class="WpfApplication1.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:sys="clr-namespace:System;assembly=mscorlib" 5 Title="MainWindow" Height="350" Width="525"> 6 <Window.Resources> 7 <Style x:Key="childStyle" TargetType="Control"> 8 <Setter Property="Background" Value="BurlyWood"/> 9 <Style.Triggers> 10 <!-- 绑定当前的radio单选框,如果按钮选中,触发字体设置 --> 11 <DataTrigger Binding="{Binding ElementName=radio, Path=IsChecked}" Value="True"> 12 <Setter Property="FontSize" Value="20"/> 13 </DataTrigger> 14 </Style.Triggers> 15 </Style> 16 </Window.Resources> 17 <Grid> 18 <RadioButton Style="{StaticResource ResourceKey=childStyle}" 19 Name="radio" Content="我要变成20号字"></RadioButton> 20 </Grid> 21 </Window>
效果:
=>
当我们选中radio的时候,字体变大,同样MultiDataTrigger这个多条件的使用道理也是一样的,这里就不介绍了。
<3>EventTrigger
这个trigger与动画有关,目前项目中还没接触到,留给大家自己研究研究。
5:IsSealed
用于标记style是只读的,类似我们在C#中的Seal关键字,来达到不允许让继承类使用,wpf使用seal常常在C#代码里面控制,在xaml中我们
是找不到的,有兴趣的话,大家自己研究研究。