代码改变世界

WPF学习(5) – 样式、模板、皮肤、主题

2012-08-29 17:40  JustRun  阅读(3653)  评论(0编辑  收藏  举报

1. 样式

1.1 样式的基本使用

样式类似于html中的样式,用来提取出来共用的一些外观属性,一般其它地方共享。style是一组Setter的集合。

一个简单的例子:

<StackPanel Orientation="Horizontal" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<StackPanel.Resources>
<Style x:Key="buttonStyle">
    <Setter Property="Button.FontSize" Value="22"/>
    <Setter Property="TextBox.Background" Value="Black"/>
    <Setter Property="Button.Background" Value="Purple"/>
    <Setter Property="TextBox.Foreground" Value="White"/>
    <Setter Property="Button.Height" Value="50"/>
</Style>

</StackPanel.Resources>
    <Button Style="{StaticResource buttonStyle}">1</Button>
    <Button Style="{StaticResource buttonStyle}">2</Button>
    <Button Style="{StaticResource buttonStyle}">3</Button>
    <TextBox Style="{StaticResource buttonStyle}"></TextBox>
</StackPanel>

 

使用样式的特点:

* 当Style被应用到一个没有默写属性的元素上的时候,它只会对存在的属性进行设置,不存在的则会被忽略。

* Sytle还有一个不确定性,比如上面定义的TextBox.Background为Black不起作用,应该是被下面的Button.Background覆盖了。这些产生的原因还不确定,为了避免这种情况,建议为不同的类型创建不同的Style

* 限制Style的使用范围。可以设置TargetType属性来限制Style只能应用于特定的控件。

* 隐式Style,也叫类型化样式, 就是没有指定key的Style, 那么该Style会被默认的应用到所有的目标类型元素。类型化样式的有效范围是由Style资源的位置决定的。

 

1.2 触发器

三种类型的触发器:

  • 属性触发器, 当依赖属性的值改变时调用
  • 数据触发器,当普通.net属性值改变时调用
  • 事件触发器,当路由事件被触发时调用

 

我们可以使用属性触发器和数据触发器来设置不同的Style。

 

一个属性触发器的例子:

<StackPanel Orientation="Horizontal" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200">
<StackPanel.Resources>

          <Style TargetType="{x:Type TextBox}">

               <Style.Triggers>

                     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value="disabled">

                            <Setter Property="IsEnabled" Value="False"/>

                     </DataTrigger>

               </Style.Triggers> 

               <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>      
               <Setter Property="Width" Value="200"/>      
          </Style>

</StackPanel.Resources>

<TextBox Margin="3"/>

</StackPanel>

 

2. 模板

目前来看,你只能通过修改控件的属性来修改外观,但是实际上可以使用控件模板来随意的改造控件。

它的原理是模板允许你用空想出来的任何东西完全替换一个元素的可视树,但其它的功能不会受到影响。

 

一个使用控件模板的例子,一个漂亮的圆形Button

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid.Resources>
    <ControlTemplate x:Key="buttonTemplate">
      <Grid>
        <Ellipse Width="100" Height="100">
          <Ellipse.Fill>
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
              <GradientStop Offset="0" Color="Blue"/>
              <GradientStop Offset="1" Color="Red"/>
            </LinearGradientBrush>
          </Ellipse.Fill>
        </Ellipse>
        <Ellipse Width="80" Height="80">
          <Ellipse.Fill>
            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
              <GradientStop Offset="0" Color="White"/>
              <GradientStop Offset="1" Color="Transparent"/>
            </LinearGradientBrush>
          </Ellipse.Fill>
        </Ellipse>
      </Grid>
    </ControlTemplate>
  </Grid.Resources>
  <Button Template="{StaticResource buttonTemplate}">OK</Button>
</Grid>

 

在控件模板中,也可以使用Trigger和限制目标类型。

3. 皮肤

WPF并没有独特的叫做皮肤的概念,也没有一个正式的换肤概念,那是因为WPF不需要这种东西。

可以用WPF写一个动态换肤的应用程序或组件,这可以通过WPF的动态资源机制加上Style和模板来实现。

4. 主题

皮肤是跟着应用程序走的,但主题通常涉及操作系统的视觉特性,它会反映在所有程序的用户界面的元素上。

对于默认的控件模板而言,于操作系统的主题保持一致很重要。

4.1 使用系统颜色、字体和参数

当Windows主题改变时,由SystemColors, SystemFonts和SystemParameters类提供的成员会自动更新。我们可以使用它们,放到我们的样式和模板中,这是让它们融入到用户主题的一个简单方式。

4.2 创建自己的主题样式和模板

第一步把指定的资源放入不同的资源字典的XAML文件中(一个主题一个文件), 然后经编译放入程序集中。 你可以把资源字典放入主题目录(必须在项目的根目录),从而把每个资源字典指派为一个主题字典,并把它们命名为ThemeName.ThemeColor.xaml。当你的应用程序启动或者主题改变时,WPF会自动加载和应用主题字典。