zoukankan      html  css  js  c++  java
  • 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>

    后续..

  • 相关阅读:
    事事浑不着意,总得有走心的地方
    Struts2框架概述
    java算法数据结构
    shell十三问(转)
    linux:将job放在后台执行的方法
    Python性能(转)
    python collections deque
    python中的参数传递和返回值
    python中的下划线
    python学习笔记glob模块
  • 原文地址:https://www.cnblogs.com/shuang121/p/2860455.html
Copyright © 2011-2022 走看看