8天入門wpf—— 第三天 樣式


    

    說起樣式,大家第一反應肯定是css,好的,先上一段代碼。

 1 html{border:0;}
 2 ul,form{margin:0; padding:0}
 3 body,div,th,td,li,dd,span,p,a{font-size:12px; font-family:Verdana,Arial,"宋體";color:#575757;}
 4 h3,input{font-size:12px; font-family:Verdana,Arial,"宋體";color:#4465a2;}
 5 
 6 body {
 7     /*background-color:#eaeaea;*/
 8     /*e5e5e5*/
 9     /*BACKGROUND: url(../images/header_bg.jpg) #fff repeat-x;*/
10     BACKGROUND: url(../images/color_1.png) #fff repeat-x 0px -233px;
11     margin:0px;
12     padding:0px;
13 }
14 
15 ul{list-style:none;}
16 h1,h2,h4,h5,h6{ font-size:14px; color:#333;}
17 img{border:0;}
18 a {color:#333333;text-decoration:none;}
19 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。

 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 TargetType="Button">
 8             <Setter  Property="Background" Value="Pink"/>
 9             <Setter Property="FontSize" Value="22"/>
10         </Style>
11     </Window.Resources>
12     <Grid>
13         <Button Content="一線碼農"/>
14     </Grid>
15 </Window>

最后效果:

仔細看看,是不是找到了css的感覺,有人肯定要問,這不就是標簽選擇器嗎?能不能做成“id選擇器”,當然可以,我們只需要給style取一個名字,

然后在控件上引用一下就ok了。

 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="mystyle" TargetType="Button">
 8             <Setter  Property="Background" Value="Pink"/>
 9             <Setter Property="FontSize" Value="22"/>
10         </Style>
11     </Window.Resources>
12     <Grid>
13         <Button Style="{StaticResource ResourceKey=mystyle}" Content="一線碼農"/>
14     </Grid>
15 </Window>

 

現在我們添加一個label,如果我們也需要同樣的“背景色”和“字體”,那么我們是否要重新寫一個label的樣式嗎?答案肯定是否定的,聰明的你肯定會

想到”基類“。我們發現label和button都是繼承自ContentControl,都屬於內容控件,那么何不在TargetType中定義為ContentControl不就ok了嗎?

 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="mystyle" TargetType="ContentControl">
 8             <Setter  Property="Background" Value="Pink"/>
 9             <Setter Property="FontSize" Value="22"/>
10         </Style>
11     </Window.Resources>
12     <Grid>
13         <Button Style="{StaticResource ResourceKey=mystyle}" 
14                 Content="Button" Height="23" Margin="132,99,0,0" Name="button1"  Width="75" />
15         <Label Style="{StaticResource ResourceKey=mystyle}" 
16                Content="Label" Height="28" Margin="140,168,0,0" Name="label1"  />
17     </Grid>
18 </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中我們

是找不到的,有興趣的話,大家自己研究研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM