《Programming WPF》翻译 第6章 2.资源与样式
原文:《Programming WPF》翻译 第6章 2.资源与样式
WPF的样式机制以来于资源体系来定位样式。正如你在第5章看到的,样式在元素的资源片段中定义,而且样式通过其名字被引用,正如示例6-18所示:
示例6-18
 <Window x:Class="ResourcePlay.Window1" Text="ResourcePlay"
<Window x:Class="ResourcePlay.Window1" Text="ResourcePlay" xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
 <Window.Resources>
    <Window.Resources> <Style x:Key="myStyle">
        <Style x:Key="myStyle"> <Setter Property="Button.FontSize" Value="36" />
            <Setter Property="Button.FontSize" Value="36" /> </Style>
        </Style> </Window.Resources>
    </Window.Resources>
 <Grid>
    <Grid> <Button Style="{StaticResource myStyle}">Hello</Button>
        <Button Style="{StaticResource myStyle}">Hello</Button> </Grid>
    </Grid> </Window>
</Window>然而,如何定义一个样式,使之自动的应用到一个元素,而无需显示指定要引用的资源——这是可以实现的,而且非常有用——当你需要把一个样式应用到具有独特类型的所有元素上,而不是把资源引用添加到每个元素上。示例6-19对示例6-18做了一些修改,展示了隐式声明这一功能。
示例6-19
 <Window x:Class="ResourcePlay.Window1" Text="ResourcePlay"
<Window x:Class="ResourcePlay.Window1" Text="ResourcePlay" xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
 <Window.Resources>
    <Window.Resources> <Style TargetType="{x:Type Button}">
        <Style TargetType="{x:Type Button}"> <Setter Property="Button.FontSize" Value="36" />
            <Setter Property="Button.FontSize" Value="36" /> </Style>
        </Style> </Window.Resources>
    </Window.Resources>
 <Grid>
    <Grid> <Button>Hello</Button>
        <Button>Hello</Button> </Grid>
    </Grid> </Window>
</Window>注意到Button标签不再有其特定的Style属性。然而,这个样式仍然通过TargetType应用到Button上,而不是定义一个key,这个样式使用x:Type来设置TargetType,于是通知XAML为这个TargetType类提供一个System.Type对象。
如果FrameworkElement没有显示指定Style,它总是会寻找一个使用其自身类型的样式资源,作为其Target类型。
如果你建立了一些非样式的资源,例如SolidColorBrush,同时设置其x:Key为某个UI元素的类型,如果试着使用该元素的类型就会发生一个错误。这是因为你创建了一个带有TargetType的Style却没有指定x:Key,x:Key隐式地设置为同TargetType一样。这个Key用于定位style。因此,通常而言,你应该避免将x:Key设置为Type类型的对象。
因为元素会在资源中搜索它的样式,你可以利用系统级别的资源。你可以定义一个样式资源在局部范围内,如果你仅仅希望影响少量的元素;或者在一个广义范围上,例如Window.Resource;或者在应用程序的范围。而且样式可能延及到系统级别。这种样式和资源之间的联系是使用皮肤和主体的关键
6.2.1皮肤和主题
皮肤和主题都是控制UI外观的技术。主题,是一种系统级别的外观,例如Windows2000的经典外观,又如Windows XP的“Luna”主题。皮肤是一个特定于应用程序的外观,正如各种各样具有不同样式的媒体播放程序,例如WinApp和Windows Media Player
皮肤和主题都可以在WPF实现,作为一组资源应用于需要该样式的控件
既然皮肤的意图在于控制一个特定应用程序的外观,它将为标准控件提供更多的样式,可以在应用程序的指定部分定义各种各样有命名的资源。例如,音乐播放器可能使用一个ListBox用来显示歌曲列表。皮肤可以为之提供一个特定的外观而不用影响应用程序中其他的ListBox。因此应用程序可以为这个ListBox设置特定的命名的样式,同时要在这个样式中支持这个样式。对于这种特定情形,提供这样一个样式是可选择的,但是在其他情形中,应用程序需要皮肤提供提供指定的资源。例如,如果应用程序中有一个工具条,皮肤可能就需要提供资源并在其中为这个工具条定义图像。
同样,主体是用于所有应用程序,因此,其必须为所有类型的控件提供模板和样式。比较而言,一个皮肤是特定于应用程序的,所以它不必提供广泛全面的一组样式。如果应用程序并不使用每一个单独的控件类型,皮肤只需要为那些在应用程序中出现的控件提供样式。示例6-20和示例6-21为一个相当简单的皮肤,展示了xaml和相应的后台代码
示例6-20
 <ResourceDictionary x:Class="SimpleSkin.BlueSkin"
<ResourceDictionary x:Class="SimpleSkin.BlueSkin" xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns="http://schemas.microsoft.com/winfx/avalon/2005" xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" >
    > <Style TargetType="{x:Type Button}">
    <Style TargetType="{x:Type Button}"> <Setter Property="Background" Value="Blue" />
        <Setter Property="Background" Value="Blue" /> <Setter Property="Foreground" Value="White" />
        <Setter Property="Foreground" Value="White" /> </Style>
    </Style> </ResourceDictionary>
</ResourceDictionary>示例6-21
 using System;
using System;
 using System.Windows;
using System.Windows;


 namespace SimpleSkin
namespace SimpleSkin  {
{


 public partial class BlueSkin : ResourceDictionary
    public partial class BlueSkin : ResourceDictionary  {
{


 public BlueSkin( )
        public BlueSkin( )  {
{
 InitializeComponent( );
            InitializeComponent( );
 }
        }
 }
    }
 }
}
以上代码为一个按钮设置了前景色和背景色。一个更复杂的皮肤应该可以为更多的类型元素提供样式,并且提供更多的属性。更多的皮肤包括一些模板属性的设定,从而可以定义控件的外观。但是即使是在这个简单的例子中,底层的原理也都是一样的。示例6-22展示了一个UI,示例6-23则是这个UI的相应后台代码,允许皮肤的切换。(这个示例假设有2个皮肤类,BlueSkin和GreenSkin,都是使用示例6-20的技术定义的。) 示例
示例6-22
 <Window x:Class="SimpleSkin.Window1" Text="SimpleSkin"
<Window x:Class="SimpleSkin.Window1" Text="SimpleSkin"
 xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
 xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">
    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005">

 <Grid Margin="1">
    <Grid Margin="1">
 <Grid.RowDefinitions>
        <Grid.RowDefinitions>
 <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
 <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
 </Grid.RowDefinitions>
        </Grid.RowDefinitions>

 <RadioButtonList x:Name="radioSkins">
        <RadioButtonList x:Name="radioSkins">
 <TextBlock>Green</TextBlock>
            <TextBlock>Green</TextBlock>
 <TextBlock>Blue</TextBlock>
            <TextBlock>Blue</TextBlock>
 </RadioButtonList>
        </RadioButtonList>

 <Button Grid.Row="1">Hello</Button>
        <Button Grid.Row="1">Hello</Button>
 </Grid>
    </Grid>
 </Window>
</Window> using System;
using System;
 using System.Windows;
using System.Windows;
 using System.Windows.Controls;
using System.Windows.Controls;


 namespace SimpleSkin
namespace SimpleSkin  {
{


 public partial class Window1 : Window
    public partial class Window1 : Window  {
{


 public Window1( )
        public Window1( )  {
{
 InitializeComponent( );
            InitializeComponent( );

 EnsureSkins( );
            EnsureSkins( );

 radioSkins.SelectionChanged += SkinChanged;
            radioSkins.SelectionChanged += SkinChanged;
 }
        }

 static ResourceDictionary greenSkin;
        static ResourceDictionary greenSkin;
 static ResourceDictionary blueSkin;
        static ResourceDictionary blueSkin;
 static bool resourcesLoaded = false;
        static bool resourcesLoaded = false;


 private static void EnsureSkins( )
        private static void EnsureSkins( )  {
{

 if (!resourcesLoaded)
            if (!resourcesLoaded)  {
{
 greenSkin = new GreenSkin( );
                greenSkin = new GreenSkin( );
 blueSkin = new BlueSkin( );
                blueSkin = new BlueSkin( );

 resourcesLoaded = true;
                resourcesLoaded = true;
 }
            }
 }
        }


 private void SkinChanged(object o, SelectionChangedEventArgs e)
        private void SkinChanged(object o, SelectionChangedEventArgs e)  {
{

 switch (radioSkins.SelectedIndex)
            switch (radioSkins.SelectedIndex)  {
{
 :
                :
 Application.Current.Resources = greenSkin;
                    Application.Current.Resources = greenSkin;
 break;
                    break;
 :
                :
 Application.Current.Resources = blueSkin;
                    Application.Current.Resources = blueSkin;
 break;
                    break;
 }
            }
 }
        }
 }
    }
 }
}
图6-5

这种切换皮肤的方式有一个小障碍。除了使用皮肤资源,在应用程序级别也存储了一些资源,那么这些应用程序资源会在切换皮肤时丢失。现在,唯一的解决方案是保证每一个皮肤包含一份应用程序级别的资源副本。最好的办法是将这些副本保存在一个单独的类,并将副本和并到资源皮肤中。WPF当前的版本不支持自动和并资源字典,WPF团队的成员已经声明,他们正在考虑更容易的处理办法在未来的发布版本中。目前,只能手动处理,正如示例6-24所示。
示例6-24
 ResourceDictionary skinResources = new FooSkinResources( );
ResourceDictionary skinResources = new FooSkinResources( ); ResourceDictionary nonSkinAppResources = new DrawingResources( );
ResourceDictionary nonSkinAppResources = new DrawingResources( );

 foreach (DictionaryEntry de in nonSkinAppResources)
foreach (DictionaryEntry de in nonSkinAppResources)  {
{ skinResources.Add(de.Key, de.Value);
    skinResources.Add(de.Key, de.Value); }
}如上,你可以将代码添加到加载资源的方法中。在示例6-23中,你可以在EnsureSkins方法中和并资源,将blue和green皮肤都和并到nonSkinAppResources中。
《Programming WPF》翻译 第6章 2.资源与样式的更多相关文章
- 《Programming WPF》翻译 第5章 4.元素类型样式
		原文:<Programming WPF>翻译 第5章 4.元素类型样式 命名样式非常有用,当你得到一组属性并应用到特点的元素上.然而,如果你想要应用一个统一的样式到所有确定元素类型的实例, ... 
- 《Programming WPF》翻译 第5章 2.内嵌样式
		原文:<Programming WPF>翻译 第5章 2.内嵌样式 每一个“可样式化”的WPF元素都有一个Style属性,可以在内部设置这个属性--使用XAML属性-元素的语法(在第一章讨 ... 
- 《Programming WPF》翻译 第5章 1.不使用样式
		原文:<Programming WPF>翻译 第5章 1.不使用样式 作为一个样式如何使其在WPF使用的例子,,让我们看一下TTT简单的实现,如示例5-1. 示例5-1 <!-- W ... 
- 《Programming WPF》翻译 第6章 3.二进制资源
		原文:<Programming WPF>翻译 第6章 3.二进制资源 尽管ResourceDictionary和系统级别的资源适合于作为数据存在于对象中,然而,并不是所有的资源都能很好的满 ... 
- 《Programming WPF》翻译 第6章 1.创建和使用资源
		原文:<Programming WPF>翻译 第6章 1.创建和使用资源 资源这个词具有非常广泛的意义.任何对象都可以是一个资源.一个在用户界面中经常使用的Brush或者Color可以是一 ... 
- 《Programming WPF》翻译 第9章 5.默认可视化
		原文:<Programming WPF>翻译 第9章 5.默认可视化 虽然为控件提供一个自定义外观的能力是有用的,开发者应该能够使用一个控件而不用必须提供自定义可视化.这个控件应该正好工作 ... 
- 《Programming WPF》翻译 第7章 3.笔刷和钢笔
		原文:<Programming WPF>翻译 第7章 3.笔刷和钢笔 为了在屏幕上绘制一个图形,WPF需要知道你想要为图形填充什么颜色以及如何绘制它的边框.WPF提供了一些Brush类型支 ... 
- 《Programming WPF》翻译 第6章 5.我们进行到哪里了?
		原文:<Programming WPF>翻译 第6章 5.我们进行到哪里了? WPF提供了资源工具,让我们运用在用户界面中,动态并具有一致性.我们可以在资源字典中存储任意资源,并且可以遍及 ... 
- 《Programming WPF》翻译 第6章 4.应用程序全球化
		原文:<Programming WPF>翻译 第6章 4.应用程序全球化 如果你打算发布你的应用程序到全球各地,你可能需要为不同地区的用户界面准备不同的版本.至少,这需要解决将文本翻译成适 ... 
随机推荐
- 【转】GitHub问题之恢复本地被删除的文件
			原文网址:http://blog.csdn.net/iaiti/article/details/39557951 折腾了真久,GitHub commit之后,我手痒把本地的一个文件给删了,然后一直gi ... 
- 【转】Install SmartGit via PPA in Ubuntu 13.10/13.04/12.04/Linux Mint
			原文网址:http://ubuntuhandbook.org/index.php/2013/09/install-smartgit-via-ppa-ubuntu-linux-mint/ This tu ... 
- bzoj3038 上帝造题的七分钟2
			Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部. "第一分钟,X说,要有数列,于是便给定了一个正整数数列. 第二分钟,L说,要能修改,于是便有了对 ... 
- POJ3580---SuperMemo (Splay)
			各种操作,区间更新,求最值.翻转.插入.删除.当然是Splay这种神器了. 主要是 revolve这个操作,其实也就是3个区间翻转放到一块, 比如 REVOLVE x y T,T %= (y-x+1) ... 
- HTML5 拼图游戏
			点击之后被选中的切片会变为透明 源代码 点击打开链接 
- Android——ViewPager多页面滑动切换以及动画效果
			一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式,白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了, ... 
- inline-block及解决空白间距
			參考:http://www.jb51.net/css/76707.html http://www.webhek.com/remove-whitespace-inline-block/ inline-b ... 
- WebService-使用JDK开发WebService
			一.使用JDK开发WebService 2.1.开发WebService服务器端 1.定义一个interface,使用@WebService注解标注接口,使用@WebMethod注解标注接口中定义的所 ... 
- ffmpeg + sdl -03 简单音频播放器实现
			没办法,工作中遇到了问题. 目前NEC EMMA的架构如下: 从USB读入文件 -> 文件分析并提取Packet中的Payload Data -> NEC HANDLE AVTrans ... 
- 开源 免费 java CMS - FreeCMS1.5-系统配置
			下载地址:http://code.google.com/p/freecms/ 系统配置 从FreeCMS 1.2 开始支持 管理系统使用的配置项. 从左侧管理菜单点击系统配置进入. 从FreeCMS ... 
