• WPF编程学习——样式


     样式(Style),主要是用来让元素或内容呈现一定外观的属性。WPF中的样式的作用,就像Web中的CSS一样,为界面上的元素定制外观,以提供更好的用户界面。在WPF应用程序中,通过控件的属性,我们也可以实现更改控件的外观。但是,这种方式局限性大、不灵活且不利于维护。例如:  

        <Grid>
    <Button Width="80" Height="30" FontSize="16" FontWeight="Bold" Margin="140,32,78,139">Button1</Button>
    <Button Width="80" Height="30" FontSize="16" FontWeight="Bold" Margin="38,86,180,84">Button2</Button>
    <Button Width="80" Height="30" FontSize="16" FontWeight="Bold" Margin="38,32,180,139">Button3</Button>
    </Grid>

      上面只有三个按钮,倘若数十个按钮、或者整个应用程序中所有的按钮,我们都这样给它们编写相同的属性,无疑很麻烦且不利维护。如果我们将上述Button的属性归纳起来,写到一段样式中,为按钮指定该样式(甚至用元素类型样式时,都不需要指定按钮样式),所有按钮就具有统一样式和外观了。如果想修改按钮外观,我们只需要改一下样式代码即可,所有按钮外观都会随之变化。

    2.怎样使用样式

      样式的使用有多种方法,如内联样式(定义在元素内部)、已命名样式(为样式命名,使用时通过名称引用)、元素类型样式(为一种类型的元素,指定一种样式)等等。

    3.内联样式

      内敛样式,是在元素定义时,在元素内部通过拓展属性Style来定义样式。

    复制代码
            <Button>
    <Button.Style>
    <Style>
    <Setter Property="Button.FontSize" Value="16"></Setter>
    <Setter Property="Button.Width" Value="80"></Setter>
    <Setter Property="Button.Height" Value="40"></Setter>
    <Setter Property="Button.Content" Value="Button"></Setter>
    </Style>
    </Button.Style>
    </Button>
    复制代码

      内联样式的缺点在于,如果想为多个元素指定同一种样式,不得不在每个元素内部都编写同一种样式,这样不但耗费人力,并且后期维护性差。就像网页中的内联CSS一样。所以,一般我们将样式放到资源中,在元素定义时,为其指定一个样式(见下文 已命名样式);或者在资源中,为某一类型的元素指定一个样式(见下文 元素类型样式)。

    4.已命名样式

      将相同的内敛样式归纳起来,放入资源中,构成一个样式,并为它起一个名字。这样,就可以通过名字为元素指定该样式。

    复制代码
        <Window.Resources>
    <Style x:Key="Style1">
    <Setter Property="Button.FontSize" Value="16"></Setter>
    <Setter Property="Button.Width" Value="180"></Setter>
    <Setter Property="Button.Height" Value="30"></Setter>
    </Style>
    </Window.Resources>
    <Grid>
    <Button Style="{StaticResource Style1}" Margin="23,32,95,139">Button1</Button>
    </Grid>
    复制代码

      指定目标类型(TargetType)

      如果给样式指定一种类型,则属性中的名字可以去掉,上述代码可改成:

    复制代码
        <Window.Resources>
    <Style x:Key="Style1" TargetType="{x:Type Button}">
    <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>
    </Grid>
    复制代码

      上述中的TargetType可以改成Control ,因为Button是从Control派生而来的。同时,CheckBox也是派生自Control,所以将Style1指定给CheckBox也是合适的。这样就能使多种元素共用一种样式。

    复制代码
        <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>
    复制代码

      

    5.元素类型样式

      一般来说,我们希望用户界面上的控件拥有统一外观,比如所有按钮大小相同、颜色一致等,这时我们可以定义一种元素的样式,对一个范围内的所有元素都有效,这就是元素类型样式。

      同一类型元素共享外观

      倘若希望一个顶级窗口内所有的元素,具有相同的样式和外观——可以这样实现: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>  
    复制代码

    6.编程控制样式

      通过代码更改按钮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");
    }

        

    7.触发器

       样式(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>
    复制代码

      多属性触发器

    复制代码
        <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.Resources>
    <Style TargetType="Button">
    <Style.Triggers>
    <DataTrigger Binding="{Binding Path=Name}" Value="李宝亨">
    <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>
    复制代码

      定义的Person类

    复制代码
        public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();
    DataContext = new Person("李宝亨","21");
    }
    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>
    复制代码

        

      以上代码监听MouseEnter事件,当鼠标经过按钮时,按钮的透明度在3秒内从1降到0.1。转于http://www.cnblogs.com/libaoheng/archive/2011/11/20/2255963.html

  • 相关阅读:
    tensorflow日志信息如何屏蔽?
    测试图像篡改模型fps逐渐降低的原因?
    np.float32()和np.float64
    hive on spark运行时 ,读取不到hive元数据问题
    Hadoop之HDFS(二)HDFS工作机制和集群安全模式
    Spark中的Driver和Executor详解及相关调优
    Linux查看物理CPU个数、核数、逻辑CPU个数
    shell命令查看进程id,并杀死进程,停止脚本
    Flink CDC 2.0 正式发布,详解核心改进
    Kafka 如何保证消息的消费顺序一致性
  • 原文地址:https://www.cnblogs.com/BoYu045535/p/3079923.html
Copyright © 2020-2023  润新知