WPF 樣式的應用


       前面簡單的說到了wpf中幾種樣式的用法,wpf有着類似web中的CSS一樣,為界面上的元素定制外觀,以提供更好的用戶界面,這種靈活性也是winForm所不能及的,從前面講到的可以知道在WPF應用程序中,通過控件的屬性,我們也可以實現更改控件的外觀。但是,這種方式局限性大、不靈活且不利於維護,比如一個,二個按鈕的樣式可以這樣,如果有二十,三十個,甚至更多,難道也這樣嗎,顯然這不是很好的選擇,如果我們將上述控件的屬性歸納起來,寫到一段樣式中,為按鈕指定該樣式(甚至用元素類型樣式時,都不需要指定按鈕樣式),所有按鈕就具有統一樣式和外觀了。如果想修改按鈕外觀,我們只需要改一下樣式代碼即可,所有按鈕外觀都會隨之變化。

樣式的使用有多種方法,如內聯樣式(定義在元素內部)、已命名樣式(為樣式命名,使用時通過名稱引用)、元素類型樣式(為一種類型的元素,指定一種樣式)等等。

一、內聯樣式

比如下面的為textBox加樣式

<TextBox Text="內容">
            <TextBox.Style>
                <Style>
                    <Setter Property="TextBox.FontSize" Value="16"></Setter>
                    <Setter Property="TextBox.Width" Value="80"></Setter>
                    <Setter Property="TextBox.Height" Value="40"></Setter>
          
                </Style>
            </TextBox.Style>
        </TextBox>

就是說,我們可以通過在元素內部通過拓展屬性Style來定義樣式。但是缺點也是顯而易見的,如果有多個這樣的控件指向同一個樣式,該怎么辦呢,只能每個都要寫,所以很不好,所以我們可以在資源中定義一個樣式,然后讓多個控件調用這一個樣式即可

二、已命名樣式

 將相同的內斂樣式歸納起來,放入資源中,構成一個樣式,並為它起一個名字。這樣,就可以通過名字為元素指定該樣式。

  <Window.Resources>
        <Style x:Key="buttonStyle">
            <Setter Property="Foreground" Value="#999999"/>
        </Style>
    
    </Window.Resources>

然后調用即可

 <Button Content="Button" Height="23" Style="{StaticResource buttonStyle}"  
HorizontalAlignment
="Left" Margin="10,204,0,0" Name="button5" VerticalAlignment="Top" Width="75" />

如果給樣式指定一種類型,則屬性中的名字可以去掉,加上指定目標類型(TargetType)

    <Window.Resources>
        <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="#999999"/>
        </Style>
    </Window.Resources>

 上述中的TargetType可以改成Control ,因為Button是從Control派生而來的。

如果其他控件也是派生自Control可以將Style1指定給這些控件也是合適的。這樣就能使多種元素共用一種樣式。

如:

  <Window.Resources>  
      <Style x:Key="Style1" TargetType="{x:Type Control }">          
  <Setter Property="FontSize" Value="16"></Setter>            <Setter Property="Width" Value="180"></Setter>   
         <Setter Property="Height" Value="30">
</Setter>       
 </Style>    
</Window.Resources>   
 <Grid>        
<Button Style="{StaticResource Style1}" Margin="23,32,95,139">Button1</Button>   
     <CheckBox Style="{StaticResource Style1}" Margin="23,130,95,41">Checkbox1</CheckBox> 
   </Grid>

 Button、Check可以使用Style1,而TextBlock則不行,原因是TextBlock不是派生自Control。

重用樣式(Reusing Styles)

  重用樣式指的是,樣式可以擁有目標所沒有的屬性。比如,我們想定義一種樣式,其中含有不想被所有元素共享的屬性,而只希望這些非共享屬性應用到特定的元素上。這時,我們就可以去掉目標類型,重新加上前綴。

    <Window.Resources>     
   <Style x:Key="Style1">   
         <Setter Property="CheckBox.FontSize" Value="16"></Setter>        
    <Setter Property="Button.Foreground" Value="Red"></Setter>    
        <Setter Property="CheckBox.IsChecked" Value="True"></Setter>     
   </Style>  
  </Window.Resources>  
  <Grid>      
  <CheckBox Style="{StaticResource Style1}" Margin="23,32,95,139">Button1</CheckBox>     
   <TextBlock Style="{StaticResource Style1}">TextBlock1</TextBlock>  
  </Grid>

 將Style1同時指定給CheckBox1和TextBlock1,TextBlocak會自動忽略不適用它們自身的樣式屬性IsChecked。而二者公有的屬性(比如Foreground、FontSize),不論加不加前綴,對二者都有效。

重寫樣式(Overriding Style)

  重寫樣式屬性類似於面向對象中的重寫,其效果也類似於CSS中的樣式覆蓋。最終的外觀取決於最近的樣式或者屬性。比如,給一個元素指定了一個樣式,其中包含FontSize屬性值為14。而在元素定義時,重新給它的屬性FontSize設置了一個值18。最終元素文本的FontSize將為18。

 

  <Window.Resources>     
   <Style x:Key="Style1">    
        <Setter Property="Button.FontSize" Value="14"></Setter>    
    </Style>  
  </Window.Resources>   
 <Grid>       
 <Button Width="80" Height="30" FontSize="18">Button1</Button>   
 </Grid>

 拓展樣式(Extending Styles)

  可以對現有樣式進行拓展,類似於面向對象中的繼承或派生,可以在添加新的屬性或者重載已存在的屬性。

  <Window.Resources>      
  <Style x:Key="Style1" TargetType="Button">
            <Setter Property="FontSize" Value="16"></Setter>  
<Setter Property="Foreground" Value="Red"></Setter> </Style> <Style x:Key="Style2" BasedOn="{StaticResource Style1}" TargetType="Button"> <!--添加新屬性--> <Setter Property="FontWeight" Value="Bold"></Setter> <!--重載--> <Setter Property="Foreground" Value="Yellow"></Setter>
</Style> </Window.Resources> <Grid> <Button Style="{StaticResource Style1}" Width="80" Height="30" FontSize="18" Margin="109,55,109,116">Button1</Button>
<Button Style="{StaticResource Style2}" Width="80" Height="30" FontSize="18" Margin="109,120,109,51">Button2</Button>
</Grid>

三、元素類型樣式

 一般來說,我們希望用戶界面上的控件擁有統一外觀,比如所有按鈕大小相同、顏色一致等,這時我們可以定義一種元素的樣式,對一個范圍內的所有元素都有效,這就是元素類型樣式。

  同一類型元素共享外觀

  倘若希望一個頂級窗口內所有的元素,具有相同的樣式和外觀——可以這樣實現:1.在頂級窗口資源中定義一個樣式,不標記x:Key,將TargetType設置為一種元素類型。2.定義元素,不用指定Style,窗口中所有該類型的元素,都將使用資源中定義的樣式,並具有統一外觀。

<Window.Resources>    
    <!--Button 樣式-->     
   <Style TargetType="{x:Type Button}">  
          <Setter Property="FontWeight" Value="Normal"></Setter>          
  <Setter Property="Foreground" Value="Green"></Setter>      
</Style> <!--TextBlock 樣式--> <Style TargetType="TextBlock"> <Setter Property="FontSize" Value="16"></Setter>
<Setter Property="Foreground" Value="Red"></Setter>
</Style>
</Window.Resources>
<Grid> <Button Name="Button1" Width="80" Height="30" Margin="46,41,172,130">Button1</Button> <Button Name="Button2" Width="80" Height="30" Margin="46,90,172,80">Button2</Button> <TextBlock Name="TextBlock1" Margin="164,41,38,0" Height="30" VerticalAlignment="Top">TextBlock1</TextBlock>
<TextBlock Name="TextBlock2" Margin="164,90,38,80">TextBlock2</TextBlock> </Grid>

 作用范圍

  以上的共享外觀不僅僅局限於頂級窗口,而是根據你定義的樣式所在的范圍。如果你將樣式定義在一個面板資源中,共享外觀將僅僅作用該面板。

  窗口范圍(作用於該窗口)

 

<Window ...>
    <Window.Resources>
        <!--Button 樣式-->
        <Style TargetType="{x:Type Button}">
            <Setter Property="Foreground" Value="Green"></Setter>
        </Style>           
    </Window.Resources>
</Window>

面板范圍(作用於該面板)

<Grid>
        <Grid.Resources>
            <!--Button 樣式-->
            <Style TargetType="{x:Type Button}">
                <Setter Property="Foreground" Value="Green"></Setter>
            </Style>
        </Grid.Resources>
        <!---->
    </Grid>

 應用程序范圍(作用於該應用程序)

<Application ...>   
 <Application.Resources>     
   <!--Button 樣式-->   
     <Style TargetType="{x:Type Button}">    
        <Setter Property="Foreground" Value="Green">
</Setter>      
  </Style>  
  </Application.Resources>
</Application>  

四、編程控制樣式

通過代碼更改按鈕Button1的樣式:

<Window.Resources>
        <!--Style1-->
        <Style x:Key="Style1" TargetType="{x:Type Button}">
            <Setter Property="FontWeight" Value="Normal"></Setter>
            <Setter Property="Foreground" Value="Green"></Setter>
        </Style>
        <!--Style2-->
        <Style x:Key="Style2" TargetType="{x:Type Button}">
            <Setter Property="FontWeight" Value="Bold"></Setter>
            <Setter Property="Foreground" Value="Red"></Setter>                        
        </Style>
    </Window.Resources>

    <Grid>
        <Button Name="Button1" Width="100" Height="40" Style="{StaticResource Style1}">Button</Button>        
        <Button Name="Button2" Width="150" Height="30" Click="Button2_Click" Margin="79,143,69,28">Change Button1's Style</Button>
    </Grid>
private void Button2_Click(object sender, RoutedEventArgs e)
{
this.Button1.Style = (Style)FindResource("Style2");
}

 五、觸發器

樣式(Styles)由三部分構成:設置器(Setter)、觸發器(Triggers)、資源(Resources)。觸發器,讓樣式的使用更加准確、靈活和高效。觸發器(Triggers)主要分為三類,屬性觸發器(檢查從屬屬性即WPF元素自身屬性)、數據觸發器(檢查任意可綁定的屬性)、事件觸發器(用於監聽事件)。

屬性觸發器

  檢查從屬屬性的值,即WPF元素自身屬性。比如按鈕的內容、字體的大小、顏色等等。

<Window.Resources> 
       <Style TargetType="Button">    
        <Style.Triggers>           
     <Trigger Property="Content" Value="按鈕">         
<Setter Property="ToolTip" Value="這是一個按鈕"> </Setter> </Trigger> </Style.Triggers> </Style> </Window.Resources>
 <Button Content="按鈕" Height="23" HorizontalAlignment="Left" Margin="28,6,0,0" Name="button1" VerticalAlignment="Top" Width="102" />

注意的是: <Trigger Property="Content" Value="按鈕">        一定要和<Button Content="按鈕"..   content的值一樣,否則掉不出來
 

多屬性觸發器

 <Window.Resources> 
       <Style TargetType="Button">      
      <Style.Triggers>     
           <Trigger Property="Content" Value="按鈕">             
<Setter Property="ToolTip" Value="這是一個按鈕"></Setter> </Trigger> <Trigger Property="Content" Value="Button">
<Setter Property="ToolTip" Value="This is a button"></Setter> </Trigger> </Style.Triggers> </Style> </Window.Resources>

多條件屬性觸發器

  <Window.Resources>   
     <Style TargetType="Button">   
         <Style.Triggers>        
        <MultiTrigger>           
         <!--條件列表-->            
        <MultiTrigger.Conditions>        
                <Condition Property="Content" Value="按鈕"></Condition>      
                
  <Condition Property="Visibility" Value="Visible"></Condition>                    </MultiTrigger.Conditions>       
             <!--樣式-->           
         <Setter Property="ToolTip" Value="這是一個可見按鈕"></Setter>            
    </MultiTrigger>       
     </Style.Triggers>    
    </Style>  
  </Window.Resources>

 數據觸發器

  可以檢查任意可綁定的屬性,比如CLR對象屬性、XPath聲明等。相對於屬性觸發器,數據觸發器通常用來檢查不可見的對象屬性。

   

<Window x:Class="WpfApplication2.樣式的用法.styleDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="styleDemo" Height="300" Width="300">
    <Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Name}" Value="dd">
                    <Setter Property="Foreground" Value="Tomato"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Content="{Binding Path=Name}" Height="23" Margin="103,94,120,84" Name="button1" Width="75"/>
    </Grid>
</Window>
  public partial class styleDemo : Window
    {
        public styleDemo() 
        {
            InitializeComponent(); 
            DataContext = new Person("dddd", "dd"); }

        class Person { 
            string _Name;
            public string Name { get { return _Name; }
            set { _Name = value; } }
            string _Age; 
            public string Age { get { return _Age; } 
                set { _Age = value; } }
            public Person(string name, string age) 
            { _Name = name; _Age = age; } }
    }

多條件數據觸發器

<Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
                <MultiDataTrigger>
                    <!--條件列表-->
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name}" Value="李寶亨"/>
                        <Condition Binding="{Binding Path=Age}" Value="21"/>
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Foreground" Value="Tomato"/>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <Button Content="{Binding Path=Name}" Height="23" Margin="103,94,120,84" Name="button1" Width="75"/>
    </Grid>

事件觸發器

<Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>
                <!--事件觸發器-->
                <EventTrigger RoutedEvent="MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.1" Duration="0:0:3"></DoubleAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

后續..


免責聲明!

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



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