博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF程序设计指南:Style
阅读量:5011 次
发布时间:2019-06-12

本文共 15290 字,大约阅读时间需要 50 分钟。

注:一下内容及代码基本来自Charles Petzold著,蔡学庸译,电子工业出版社出版的《Windows Presentation Foundation 程序设计指南》一书

1. Style概述

  • Style是Property值的collection,这些Style的property值可以用在element上,Style可以一定程度弥补XAML无法使用循环语句的缺点。
  • 最重要的Property是, 类型为,这是的集合,
  • 是一个抽象类的子类有和

因此,最基本的Style格式是:

 
<
Style
...
>
<
Setter
...
/>
<
EventSetter
...
/>
<
Setter
...
/>
</
Style
>

2. Style属性之一

  • 一个或者多个 or objects
  • 主要用来设置element的一个与“值”相关的Property
  • 主要有两个Property: Property 和 Value 
  • 如果是在c#代码里,需要将Properyt设置为FontSizeProperty

  • 如果需要将Value设置为null:Value="{x:Null}"

3. 关于对Property设置的优先级

  •  如有一个仅供某个element使用的Style(这样设置用处不大,仅为举例) 
代码
 
<
Button
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
HorizontalAlignment
="Center"
VerticalAlignment
="Center"
Foreground
="Red"
>
<
Button.Style
>
<
Style
>
<
Setter
Property
="Button.FontSize"
Value
="18pt"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
</
Style
>
</
Button.Style
>
Button with Local Style
</
Button
>
  • 如果像这样,在element中和Style中都对Foreground做设定,那么“局部设定”的优先级优先于Style的设定
  • 而Style的优先级又高于从visual tree 继承来的Property设定

4. Style作为Resource使用

 如下,一个由Button控件和TextBlock element共用的Style

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
x:Key
="normal"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
<
Setter
Property
="Control.Padding"
Value
="20, 10, 20, 10"
/>
</
Style
>
</
StackPanel.Resources
>
<
Button
Style
="{StaticResource normal}"
>
Button on top of the stack
</
Button
>
<
TextBlock
Style
="{StaticResource normal}"
>
TextBlock in the middle of the stack
</
TextBlock
>
<
Button
Style
="{StaticResource normal}"
>
Button on the bottom of the stack
</
Button
>
</
StackPanel
>

 也可以为某个独有的Property定义一个Setter。例如:

 
<
Setter
Property
="Button.IsDefault"
Value
="true"
/>

 只会设置Button的IsDefault,因为TextBlock不具有此属性

 5. 具有相同key的style

 可以在多个resource中使用相同的key来定义stlye。对于某个特定的element来说,它将沿视觉树往上搜索,采用第一个和key关联的style。 

代码
 
<
Grid
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
Grid.Resources
>
<
Style
TargetType
="{
x:Type Button}"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
</
Style
>
</
Grid.Resources
>
<
StackPanel
>
<
StackPanel.Resources
>
<
Style
TargetType
="{
x:Type Button}"
>
<
Setter
Property
="Control.Foreground"
Value
="Red"
/>
</
Style
>
</
StackPanel.Resources
>
<
Button
>
Button Number 1
</
Button
>
<
Button
>
Button Number 2
</
Button
>
<
Button
>
Button Number 3
</
Button
>
</
StackPanel
>
</
Grid
>

 说明: 

这些按钮会使用在StackPanel中定义的style,前景色为红色,字体为默认值。

使用相同名称的style不会覆盖某些property的同时还去保留另外一些。

 6. Style属性之二:Resource

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
x:Key
="normal"
>
<
Style.Resources
>
<
LinearGradientBrush
x:Key
="gradbrush"
StartPoint
="1,0"
EndPoint
="1,1"
>
<
LinearGradientBrush.GradientStops
>
<
GradientStop
Color
="LightBlue"
Offset
="0"
/>
<
GradientStop
Color
="Aquamarine"
Offset
="1"
/>
</
LinearGradientBrush.GradientStops
>
</
LinearGradientBrush
>
</
Style.Resources
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
<
Setter
Property
="Control.Background"
Value
="{StaticResource gradbrush}"
/>
</
Style
>
</
StackPanel.Resources
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 1
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 2
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 3
</
Button
>
</
StackPanel
>

 以上代码,如果不使用Resource,就要将value打散:

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
x:Key
="normal"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
<
Setter
Property
="Control.Background"
>
<
Setter.Value
>
<
LinearGradientBrush
StartPoint
="1,0"
EndPoint
="1,1"
>
<
LinearGradientBrush.GradientStops
>
<
GradientStop
Color
="LightBlue"
Offset
="0"
/>
<
GradientStop
Color
="Aquamarine"
Offset
="1"
/>
</
LinearGradientBrush.GradientStops
>
</
LinearGradientBrush
>
</
Setter.Value
>
</
Setter
>
</
Style
>
</
StackPanel.Resources
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 1
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 2
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 3
</
Button
>
</
StackPanel
>

7. Style属性之三:TargetType

TargetType,指定此style被用到何种类型的element上。

被应用的element必须“类型完全符合”,例如,如果TargetType为Control,则此Sytle不会采用到Button或者label控件上。

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
TargetType
="{
x:Type Button}"
>
<
Setter
Property
="FontSize"
Value
="24"
/>
<
Setter
Property
="Foreground"
Value
="Blue"
/>
</
Style
>
<
Style
TargetType
="{
x:Type TextBlock}"
>
<
Setter
Property
="Foreground"
Value
="Red"
/>
</
Style
>
</
StackPanel.Resources
>
<
Button
>
Button with Text Content
</
Button
>
<
TextBlock
>
TextBlock Text
</
TextBlock
>
<
Button
>
<
TextBlock
>
Button with TextBlock Content
</
TextBlock
>
</
Button
>
</
StackPanel
>

说明:

第一个element:<Button>采用第一个style。前景色为蓝色,字体为24

第二个element:<TextBlock>采用第二个style。前景色为红色,字体为默认值

第三个element:<Button>中的<TextBlock>,前景色会采用第二个style(红色),而字体为24。原因是Sytle比“property继承”优先级高,所以前景色用第二个style,但是由于该style中没有对字体设定,所以会继承视觉树上其父亲的此property。

 

注:

  • 可以在指定TargertType的同时指定Key
  • 只要指定了TargertType,特定Type的element就一定会使用特定的style(同一个TargetType的style,有的style有key,有的style没有key,那么没有指定key的element也会用没有指定key的style)
  • 如果多个style被定义在同一个resource section,他们的key不可以重复

8. Style属性之四:BasedOn

    BasedOn有类似“继承”的作用,可以修改已有的Style:

  • 通过指定已有的Style的key,或者TargetType来实现:
    代码
     
    <
    StackPanel
    xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
    >
    <
    StackPanel.Resources
    >
    <
    Style
    x:Key
    ="normal"
    >
    <
    Setter
    Property
    ="Control.FontSize"
    Value
    ="24"
    />
    <
    Setter
    Property
    ="Control.Foreground"
    Value
    ="Blue"
    />
    <
    Setter
    Property
    ="Control.HorizontalAlignment"
    Value
    ="Center"
    />
    <
    Setter
    Property
    ="Control.Margin"
    Value
    ="24"
    />
    <
    Setter
    Property
    ="Control.Padding"
    Value
    ="20, 10, 20, 10"
    />
    </
    Style
    >
    <
    Style
    TargetType
    ="{x:Type Button}"
    >
    <
    Setter
    Property
    ="Control.FontSize"
    Value
    ="24"
    />
    <
    Setter
    Property
    ="Control.Foreground"
    Value
    ="Blue"
    />
    <
    Setter
    Property
    ="Control.HorizontalAlignment"
    Value
    ="Center"
    />
    <
    Setter
    Property
    ="Control.Margin"
    Value
    ="24"
    />
    </
    Style
    >
    <
    Style
    x:Key
    ="hotbtn"
    TargetType
    ="{x:Type Button}"
    BasedOn
    ="{StaticResource {x:Type Button}}"
    >
    <
    Setter
    Property
    ="Control.Foreground"
    Value
    ="Red"
    />
    </
    Style
    >
    <
    Style
    x:Key
    ="newbtn"
    BasedOn
    ="{StaticResource normal}"
    >
    <
    Setter
    Property
    ="Control.Foreground"
    Value
    ="Red"
    />
    </
    Style
    >
    </
    StackPanel.Resources
    >
    <
    Button
    Style
    ="{StaticResource normal}"
    >
    Button Number 1
    </
    Button
    >
    <
    Button
    Style
    ="{StaticResource hotbtn}"
    >
    Button Number 2
    </
    Button
    >
    <
    Button
    Style
    ="{StaticResource newbtn}"
    >
    Button Number 3
    </
    Button
    >
    </
    StackPanel
    >

      注:如果已有的Style既有key又有TargetType,那么baseon的style也要都指定

  • baseon的时候,TargetType也可以用继承
代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
TargetType
="{x:Type Control}"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
</
Style
>
<
Style
TargetType
="{x:Type Button}"
BasedOn
="{StaticResource {x:Type Control}}"
>
<
Setter
Property
="Control.Foreground"
Value
="Red"
/>
</
Style
>
<
Style
TargetType
="{x:Type Label}"
BasedOn
="{StaticResource {x:Type Control}}"
>
<
Setter
Property
="Control.Foreground"
Value
="Green"
/>
</
Style
>
<
Style
TargetType
="{x:Type TextBox}"
BasedOn
="{StaticResource {x:Type Control}}"
>
</
Style
>
</
StackPanel.Resources
>
<
Button
>
Button Control
</
Button
>
<
Label
>
Label Control
</
Label
>
<
TextBox
>
TextBox Control
</
TextBox
>
</
StackPanel
>

9. 使用Style的内在约束

  • 不能定义没有dependency property支持的值,例如不能指定一个stackpanel所具有的孩子个数(应该使用Template)
  • setter不支持派生自Visual或ContentElement的Value(例如将一张图片设为使用该style的Button的Content)。因为在特定的style中引用到的任何对象,都只会被创建一次,成为该style的一部分,所以会被使用该style的element所共有。

10. 将数据绑定应用到Style

  •  Setter 中的 Value属性可以是一个数据绑定
代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
TargetType
="{x:Type Button}"
>
<
Setter
Property
="FontSize"
Value
="{Binding ElementName=scroll, Path=Value}"
/>
<
Setter
Property
="HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Margin"
Value
="24"
/>
</
Style
>
</
StackPanel.Resources
>
<
ScrollBar
Name
="scroll"
Orientation
="Horizontal"
Margin
="24"
Minimum
="11"
Maximum
="100"
Value
="24"
/>
<
Button
>
Button Number 1
</
Button
>
<
Button
>
Button Number 2
</
Button
>
<
Button
>
Button Number 3
</
Button
>
</
StackPanel
>

以上Button的Fontsize的Value被绑定到一个名为“scroll”的ScrollBar的Value Property上。

  •  也可以搭配RelativeSource
 
<
Setter
Property
="X2"
Value
="{Binding RelativeSource={RelativeSource self},
Path=X1}"
/>

以上代码将x2属性的值绑定为和x1一样。

11. Style中的事件处理 :

 EventerSetter和Setter级别相同,用来为特定的routed事件设定事件处理函数

可以在多个element间共享一个事件处理函数

代码
 
<
Window.Resources
>
<
Style
TargetType
="{x:Type Button}"
>
<
Setter
Property
="FontSize"
Value
="24"
/>
<
Setter
Property
="HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Margin"
Value
="24"
/>
<
EventSetter
Event
="Click"
Handler
="ButtonOnClick"
/>
</
Style
>
</
Window.Resources
>
<
StackPanel
>
<
Button
>
Button Number 1
</
Button
>
<
Button
>
Button Number 2
</
Button
>
<
Button
>
Button Number 3
</
Button
>
</
StackPanel
>
</
Window
>

12. Style的第五个属性:Triggers

  1. Triggers设定element或控件如何响应“此element property 的改变”,或者“数据绑定的改变”,或者“事件的发生”
  2. Setter和Trigger都涉及“要被设定的”property。Setter是在element第一次创建时进行property设定,Trigger只有当某些事情发生时,才会去设定property(也就是说某些事情触发使得此property改变)
  3. Triggers属性的类型是TriggerCollection,这是TriggerBase对象的collection, 派生自TriggerBase类型的Trigger有五种:
    • System.Windows..::.TriggerBase  
               
                 (主要用于图形动画)
               
              
            

一下依次介绍除EventTrigger之外的各种Trigger

  • Trigger

Trigger是最常见的,用来指定control或element应该如何响应特定的propertyd的改变,这些property常常都涉及到用户的输入,例如IsMouseOver property

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
x:Key
="normal"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
<
Style.Triggers
>
<
Trigger
Property
="Control.IsMouseOver"
Value
="true"
>
<
Setter
Property
="Control.FontStyle"
Value
="Italic"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
</
Trigger
>
<
Trigger
Property
="Button.IsPressed"
Value
="true"
>
<
Setter
Property
="Control.Foreground"
Value
="Red"
/>
</
Trigger
>
</
Style.Triggers
>
</
Style
>
</
StackPanel.Resources
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 1
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 2
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 3
</
Button
>
</
StackPanel
>

说明:

   1. 当property的值被改变回去时,被Trigger修改的Property也会恢复他们原始的状态

   2. 以上两个Trigger的次序对效果有所影响,如果两个Trigger对相同的property做设定,后一个会覆盖前一个。如果以上两个Trigger对调,文字不会变成红色,因为press的时候,IsMouseOver肯定是为True的。

  • MultiTrigger

MultiTrigger只有在两个或者多个事件都成立时才会被触发

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
x:Key
="normal"
>
<
Setter
Property
="Control.FontSize"
Value
="24"
/>
<
Setter
Property
="Control.HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Control.Margin"
Value
="24"
/>
<
Style.Triggers
>
<
Trigger
Property
="Button.IsPressed"
Value
="True"
>
<
Setter
Property
="Control.Foreground"
Value
="Red"
/>
</
Trigger
>
<
MultiTrigger
>
<
MultiTrigger.Conditions
>
<
Condition
Property
="Control.IsMouseOver"
Value
="True"
/>
<
Condition
Property
="Button.IsPressed"
Value
="False"
/>
</
MultiTrigger.Conditions
>
<
Setter
Property
="Control.FontStyle"
Value
="Italic"
/>
<
Setter
Property
="Control.Foreground"
Value
="Blue"
/>
</
MultiTrigger
>
</
Style.Triggers
>
</
Style
>
</
StackPanel.Resources
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 1
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 2
</
Button
>
<
Button
Style
="{StaticResource normal}"
>
Button Number 3
</
Button
>
</
StackPanel
>

 鼠标移动到按钮上:文字蓝色

 点击按钮:文字红色

 鼠标移动到按钮上方且按钮没有被按下:文字斜体

  • DateaTrigger

DataTrigger与Trigger类似,只是用Binding取代了Property,Binding通常引用到另一个element。

代码
 
<
StackPanel
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
>
<
StackPanel.Resources
>
<
Style
TargetType
="{x:Type Button}"
>
<
Setter
Property
="FontSize"
Value
="24"
/>
<
Setter
Property
="HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Margin"
Value
="24"
/>
<
Style.Triggers
>
<
DataTrigger
Binding
="{Binding ElementName=txtbox,
Path=Text.Length}"
Value
="0"
>
<
Setter
Property
="IsEnabled"
Value
="False"
/>
</
DataTrigger
>
</
Style.Triggers
>
</
Style
>
</
StackPanel.Resources
>
<
TextBox
Name
="txtbox"
HorizontalAlignment
="Center"
Width
="2in"
Margin
="24"
/>
<
Button
>
Button Number 1
</
Button
>
<
Button
>
Button Number 2
</
Button
>
<
Button
>
Button Number 3
</
Button
>
</
StackPanel
>

以上设定,只有当TextBox中的字符数不为0,Button才会Enable

  • MultiDataTrigger

只有在多个绑定条件都成立时,才会触发事件

代码
 
<
StackPanel.Resources
>
<
Style
TargetType
="{x:Type CheckBox}"
>
<
Setter
Property
="HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Margin"
Value
="12"
/>
</
Style
>
<
Style
TargetType
="{x:Type Button}"
>
<
Setter
Property
="FontSize"
Value
="24"
/>
<
Setter
Property
="HorizontalAlignment"
Value
="Center"
/>
<
Setter
Property
="Margin"
Value
="12"
/>
<
Setter
Property
="IsEnabled"
Value
="False"
/>
<
Style.Triggers
>
<
MultiDataTrigger
>
<
MultiDataTrigger.Conditions
>
<
Condition
Binding
="{Binding ElementName=chkbox1,
Path=IsChecked}"
Value
="True"
/>
<
Condition
Binding
="{Binding ElementName=chkbox2,
Path=IsChecked}"
Value
="True"
/>
</
MultiDataTrigger.Conditions
>
<
Setter
Property
="IsEnabled"
Value
="True"
/>
</
MultiDataTrigger
>
</
Style.Triggers
>
</
Style
>
</
StackPanel.Resources
>
<
CheckBox
Name
="chkbox1"
>
Check 1
</
CheckBox
>
<
CheckBox
Name
="chkbox2"
>
Check 2
</
CheckBox
>
<
Button
>
Button Number 1
</
Button
>
<
Button
>
Button Number 2
</
Button
>
<
Button
>
Button Number 3
</
Button
>
</
StackPanel
>

 以上设定,只有两个checkbox都被选中,才会时按钮enable

转载于:https://www.cnblogs.com/mycom/archive/2010/11/29/1891165.html

你可能感兴趣的文章
windows 中的类似于sudo的命令(在cmd中以另一个用户的身份运行命令)
查看>>
java===单类设计模式之饿汉式与懒汉式
查看>>
BZOJ 1083: [SCOI2005]繁忙的都市
查看>>
Maven 编译
查看>>
《学习之道》第十章学习方法29还记得散步的好处嘛
查看>>
Git常用命令总结
查看>>
iOS获取设备IP地址
查看>>
JavaSE| String常用方法
查看>>
NRF51822配对绑定要点
查看>>
C语言博客作业—数据类型
查看>>
[leetcode]Count and Say
查看>>
cookie、session和token的概念入门
查看>>
保护网站页面内容+版权
查看>>
Golang模拟客户端POST表单功能文件上传
查看>>
重启进程
查看>>
js 进度条效果
查看>>
RelativeLayout
查看>>
注意细节
查看>>
currying 柯里化,返回函数
查看>>
ASP.NET WebForm(MVC)下实现消息推送(提供简单Demo下载)
查看>>