当前位置: 首页 > news >正文

WPF程序设计指南:Style

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

1. Style概述

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

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


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

2. Style属性之一:Setters

  • 一个或者多个Setter or EventSetter objects
  • Setter主要用来设置element的一个与“值”相关的Property
  • Setter主要有两个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中的事件处理 :EventSetter

 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  
             System.Windows..::.DataTrigger  
            System.Windows..::.EventTrigger     (主要用于图形动画)
            System.Windows..::.MultiDataTrigger   
            System.Windows..::.MultiTrigger  
            System.Windows..::.Trigger

一下依次介绍除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

相关文章:

  • 静态方法(Static)到底该不该用?
  • JS 简单的2级下拉框
  • 使用Windows 7中的库
  • 嘉猪妈妈写的日记(一)
  • QT C++ 学习
  • 理解相机的相关参数的设置
  • 带参数的main函数
  • 基本文章
  • 使用sharppcap抓数据包
  • SOA
  • Mac OS 10.6.5上如何默认启动mysq服务
  • fedora linux 下安装pwntcha[验证码开源]
  • 初识 统一建模语言(UML)
  • OllyDBG 1.10汉化第二版
  • Eclipse Android配置
  • AngularJS指令开发(1)——参数详解
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • chrome扩展demo1-小时钟
  • go append函数以及写入
  • JavaScript HTML DOM
  • uni-app项目数字滚动
  • Webpack 4 学习01(基础配置)
  • 阿里云应用高可用服务公测发布
  • 读懂package.json -- 依赖管理
  • 前端代码风格自动化系列(二)之Commitlint
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 栈实现走出迷宫(C++)
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #pragma multi_compile #pragma shader_feature
  • (4)STL算法之比较
  • (C)一些题4
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (超详细)语音信号处理之特征提取
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (一)基于IDEA的JAVA基础10
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)C#调用WebService 基础
  • (转)详解PHP处理密码的几种方式
  • ***利用Ms05002溢出找“肉鸡
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .net对接阿里云CSB服务
  • .NET建议使用的大小写命名原则
  • [ C++ ] 继承
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [Cocoa]iOS 开发者账户,联机调试,发布应用事宜
  • [codevs 1296] 营业额统计
  • [G-CS-MR.PS02] 機巧之形2: Ruler Circle
  • [ISCTF 2023]——Web、Misc较全详细Writeup、Re、Crypto部分Writeup
  • [Jquery] 实现鼠标移到某个对象,在旁边显示层。