`
bolutes
  • 浏览: 863388 次
文章分类
社区版块
存档分类
最新评论

Silverlight资源字典

 
阅读更多

资源字典是一个受 ResourceDictionary 类支持的概念。资源字典是一个键控对象字典,可在 XAML 和代码中使用。XAML 是最常见的用法,特别是用于最初定义资源字典中的对象。资源字典可存在于应用程序结构中的多个位置,包括作为直接(页)资源、应用程序资源(作为 Application 对象的一部分)或作为 XAML 文件(在应用程序项目结构中单独保存)以供稍后运行时使用,也可用作合并字典。资源字典通常支持两个主要 Silverlight 方案:定义控件模板(作为样式的一部分)和定义用于进行动画处理的属性的演示图板。

本主题包括下列各节。

适用于 JavaScript API 的 ResourceDictionary

在有限的几种情况下,还可以通过 JavaScript API 访问 ResourceDictionary。本主题不介绍这些情况。请参见 ResourceDictionary

适用于 ResourceDictionary 用法的对象

在 Silverlight 中,并非所有类/对象都适合 ResourceDictionary 用法。为了在 ResourceDictionary 中定义某个对象并从其中访问该对象,该对象必须成为可共享的对象。这是一个必要条件,因为当应用程序的对象树最终完成构造并在运行时使用时,对象不能在没有共享机制或间接机制(如引用)的情况下存在于树中的多个位置。从 UIElement 类型派生的对象本质上是不可共享的,除非该对象是从控件模板生成的。

SilverlightResourceDictionary 用法支持以下各项的可共享用法:

  • 样式和模板。

  • 画笔和颜色。

  • 包括演示图板的动画类型。

  • 转换。

  • MatrixMatrix3DPoint

  • 某些具有可设置和可构造属性的其他结构,如 ThicknessCornerRadius(但是,这些结构通常要求在 XAML 中使用初始化文本以便声明有用值;有关更多信息,请参见特定结构的"XAML 用法"部分)。

  • 在支持代码中定义然后在 XAML 中实例化为资源的自定义类型,如资源的转换器。

  • 字符串和基本数值,如 double 和 int。请注意,XAML 中对这些系统类型的对象元素用法要求您映射 System 命名空间和 mscorlib 程序集(其中基元是结构定义的)。相关语法为 xmlns:sys="clr-namespace:System;assembly=mscorlib"。有关 XAML 命名空间映射的更多信息,请参见 Silverlight XAML 命名空间以及将 XAML 命名空间映射为前缀

键和资源

ResourceDictionary 中的项必须各有一个定义的键。在 XAML 中,可通过为作为 ResourceDictionary 内容添加的对象元素的 x:Key 特性提供值来指派键。在资源字典概念的 Silverlight 实现中,ResourceDictionary 可以有 x:Name,而不是 x:Key,或者二者兼而有之。如果未指定 x:Key,则 x:Name 用作键。x:Name / x:Key 替换支持某些应用程序可能仍在使用的旧式资源字典用法。

注意说明:

如果 XAML 包含的 ResourceDictionary 所包含的项具有 x:Name,但没有 x:Key,则某些工具或开发环境可能针对该 XAML 发出警告。但是,x:Name / x:Key 替换对于运行时 XAML 分析将是有效的。

如果要在 XAML 标记中使用键控资源,通常可以通过一个 xmlns 声明映射 XAML 语言本身的 XAML 命名空间。这通常是必需的,因为 x:Namex:Key 是由 XAML 固有的 XAML 命名空间定义的。

注意说明:

Silverlight 文档假定 XAML 固有的典型映射前缀为 x:,因此文档中对"Key"的引用通常采用 x:Key 格式,同时附加假定的 x 前缀。此外,通常还在根元素级别同时映射默认 Silverlight 命名空间和 XAML 固有的 XAML 命名空间。

Silverlight ResourceDictionary 中的资源必须使用字符串作为它们的键名。有关键名的字符串值限制,请参见 XamlName 语法。Silverlight 中用于键名的值必须符合此语法。

如果您包括的项在资源字典中不具有可用键,则会发生分析器异常。当您复制键时,就会发生分析器异常。通常,如果键、无法创建的对象元素或资源查找存在问题,则在代码编译期间将检测不到这些问题,仅当 Silverlight 在运行时尝试加载 XAML 时才会将它们报告为异常。

直接资源和应用程序资源

有两个属性接受 ResourceDictionary 类型的值:FrameworkElement..::.ResourcesApplication..::.ResourcesFrameworkElement..::.Resources 提供直接资源。在 XAML 中,可以从任何满足以下条件的元素引用 FrameworkElement..::.Resources 中的键控资源:连接到这些资源所在的对象树。通常,为 XAML 页的根元素定义 FrameworkElement..::.Resources 值,并且通常而言,对于用户应用程序来说,UI 页的根元素为 UserControl。因此,常见用法是定义可由页用作 UserControl.Resources 内的元素的所有直接资源。

Application..::.Resources 提供应用程序范围的资源。无论哪个页作为应用程序的当前 RootVisual 加载,由 Application..::.Resources 定义的资源都是可用的。如果将不同的可能页加载到 RootVisual,并且需要一种方法来避免复制各个可能页中相同的资源,这可能很重要。此外,如果要在运行时将值写入资源字典,这将提供一个可以在应用程序生存期中保存这些资源的位置。

注意说明:

请不要将与 ResourceDictionary 有关的概念同 Resources 生成操作、.resx 文件以及在关于如何组织项目(在 MSBUILD 或 Visual Studio 等开发环境中生成应用程序)结构的上下文中讨论的其他"资源"相混淆。尽管生成操作和应用程序结构的资源概念可以与 ResourceDictionary 用法重叠,但是 ResourceDictionary 通常可被视为提供自包含的资源系统,该系统将 XAML 作为其主要定义格式合并进来。

从 XAML 中引用资源

在 XAML 中,可通过使用 StaticResource 标记扩展来引用现有资源。若要使用标记扩展,应始终引用通过属性 (Attribute) 用法设置的属性 (Property)。例如,若要将 ButtonBackground 属性的值设置为资源,可编写与以下 XAML 类似的代码:

复制代码

<!--item in a ResourceDictionary-->
<lineargradientbrush x:key="fadeBrush"><gradientstop color="Red" offset="0"></gradientstop><gradientstop color="Gray" offset="1"></gradientstop></lineargradientbrush><!--XAML that defines the actual UI-->

即使您设置的属性 (Property) 通常接受对象,也可以将属性 (Attribute) 语法用于资源引用,这样如果以内联方式而不是作为资源定义设置对象,将需要在 XAML 中使用属性 (Property) 元素。例如,下面是等效的属性元素用法(如果以内联方式定义 LinearGradientBrush):

复制代码

  <button.background><lineargradientbrush><gradientstop color="Red" offset="0"></gradientstop><gradientstop color="Gray" offset="1"></gradientstop></lineargradientbrush></button.background>

注意说明:

不能将 StaticResource 周围的属性元素用法显式用作对象元素内容。在 Silverlight 中,StaticResource 标记扩展仅支持用作属性值(而不支持用作对象元素)。

StaticResource 的查找行为

StaticResource 的查找行为是 XAML 的标记编译处理将首先检查应用实际用法的对象是否能够保存 FrameworkElement..::.Resources 值。如果是,将检查该 ResourceDictionary 中是否有该键所对应的项。此级别的查找并不重要,因为您通常不会在同一对象上定义并引用资源。接下来发生的情况更重要:查找过程将检查下一个对象树父级是否有 FrameworkElement..::.Resources,如果该属性存在,则检查键。该过程一直继续,直到到达了 XAML 的根元素。为了利用此行为以及作为一种标记样式,通常在页的根级别定义所有直接资源。

如果在直接资源中找不到请求的资源,则下一个查找步骤是检查 Application..::.Resources

如果在此序列之后仍然找不到所请求的键,将发生分析器异常。

基于此查找行为,可以特意定义多个具有与键相同的字符串值的资源,只要每个这样的资源都在一个不同的元素级别定义,且在该级别有一个保持键唯一性的 FrameworkElement..::.Resources 属性。只有检索到的第一个这样的对象才会用于 StaticResource。可以使用此行为在对象树的各个不同级别检索同一个 StaticResource 键,但是会得到不同的结果。

合并资源字典

从 Silverlight 3 开始,Silverlight 支持合并资源字典。使用合并资源字典可以通过引用外部文件来声明资源字典的内容。此外,合并资源字典还修改资源字典的两个特征:查找序列和键唯一性要求。

若要声明合并资源字典,需要将 MergedDictionaries 属性的属性元素添加到现有 ResourceDictionary 位置(通常为 FrameworkElement..::.Resources,但有时为 Application..::.Resources)。您必须将 ResourceDictionary 显式声明为一个对象元素才能在其中使用属性元素。现有 ResourceDictionary 可能具有其他键控资源和 MergedDictionaries 属性元素。MergedDictionaries 的内容为声明为对象元素的另一个 ResourceDictionary。但是此 ResourceDictionary 不应将更多的键控资源作为自己的内容,而应只声明一个特性:Source。您可以在 MergedDictionaries 内指定多个 ResourceDictionary

例如,下面的 XAML 定义包含一个键控资源的 ResourceDictionary 以及通过 URI 引用两个不同资源字典的 MergedDictionaries 集合:

复制代码

<grid><grid.resources><resourcedictionary><solidcolorbrush color="#d0157820" x:key="muddyBrush"></solidcolorbrush><resourcedictionary.mergeddictionaries><resourcedictionary source="/rd1.xaml"><resourcedictionary source="/rd2.xaml"></resourcedictionary></resourcedictionary></resourcedictionary.mergeddictionaries></resourcedictionary></grid.resources>
....
<grid></grid></grid>

就查找序列而言,只有在检查完声明了 MergedDictionariesResourceDictionary 的所有键控资源后才会检查 MergedDictionaries 字典。然后,会按 MergedDictionaries 内的每个字典在 MergedDictionaries 属性中的反向声明顺序逐个检查这些字典。换句话说,就是合并资源字典集合内的检索逻辑是按后进先出的顺序。

ResourceDictionary 的范围内,要检查字典的键唯一性。但是,该范围不超出 MergedDictionaries 边界。例如,可以为不同资源定义同一字符串键 muddyBrush,条件是在 ResourceDictionary 外部声明一次该键,而同一 ResourceDictionary 以源的方式引用作为合并资源字典的一些资源字典,然后可在其中任何一个资源字典内再次声明该键。在 MergedDictionaries 内,如果在主资源字典中找到该键,则会在此处停止查找。否则,会检查 MergedDictionaries 中随后声明的每个字典,最先检查最后添加的合并字典。如果仍未找到,则对朝向页面 XAML 根方向的下一个 FrameworkElement..::.Resources 以及 Application..::.Resources 范围继续查找。

可以结合使用查找序列和跨合并字典范围不强制使用唯一键来创建资源回退序列。例如,可以将特定画笔颜色的用户首选项存储在该序列的最后一个合并资源字典中。但是,如果尚不存在任何用户首选项,则可在居前的合并资源字典中定义同一键控资源,该资源可用作回退资源。

ResourceDictionary 中的前向引用

任何给定资源字典内的静态资源引用必须引用在引用资源之前已在词法上定义的资源。静态资源引用无法解析前向引用。因此,如果您使用静态资源引用,则必须设计资源字典结构,以便将进一步逐个使用的资源在各相应资源字典的开头或附近定义。

应用程序资源和直接资源之间的引用

为应用程序定义的资源不能引用直接资源。这等效于尝试前向引用,因为应用程序资源实际上是最先处理的。但是,任何直接资源都可以引用应用程序资源,这对于避免前向引用是一个很有用的技术。

资源字典和 XamlReader.Load

可以将 ResourceDictionary 用作 XamlReader..::.Load 的 XAML 输入的根或一部分。也可以在该 XAML 中包含 StaticResource 引用,前提是所有这样的引用在 XAML 中都完全是自包含的。XamlReader..::.Load 在不了解任何其他 ResourceDictionary 对象(甚至 Application..::.Resources)的上下文中分析 XAML。

模板中的 StaticResource

模板中的任何 StaticResource 都在定义模板而不是应用模板的上下文中评估。通常,这意味着模板中的 StaticResource 引用必须来自同一个 ResourceDictionary 中以前在词法上定义的其他项或来自 Application..::.Resources

从代码中引用资源

在代码中,可以使用索引器 (Item) 来引用资源。在此索引器情况下,索引器使用键,而不是整数索引。通常,先决条件是检索特定的 ResourceDictionary,或者是通过获取 FrameworkElement..::.Resources 来检索位于对象树中某处的直接 ResourceDictionary,或者是通过依次调用 Application..::.CurrentApplication..::.Resources 来检索应用程序 ResourceDictionary

注意说明:

Silverlight 不实现存在于 WPF 框架中的 FindResource 方法。

运行时用法

可以将资源字典声明为离散的 XAML 文件,然后使用 Load 以及应用程序服务中的从包加载 API 在运行时加载它。在这种情况下,ResourceDictionary 被声明为对象元素,充当 XAML 的根元素。如果您打算将 ResourceDictionary 元素用作根元素,则必须将相应的 XML 命名空间(对于 Silverlight 为默认值,对于 XAML 为 x:)映射到该元素。然后,可以为定义资源的项添加对象元素,每个项都有一个相应的键。但是,如果此 ResourceDictionary 用于提供由 XAML 中的 StaticResource 调用的资源,则必须将 ResourceDictionary 附加到现有 Resources 属性,这样它就可以加入查找序列(例如,可以使用 Startup 来设置 Application..::.Resources)。

另一个可能的运行时用法是通过调用 AddResourceDictionary 中添加项。可以向直接资源中添加,也可以向应用程序资源中添加。运行时,ResourceDictionary 与您自己创建的字典几乎没有什么区别,只是 ResourceDictionary 通常从初始 XAML 中填充,并且 ResourceDictionary 比较方便,因为您可以从现有的 FrameworkElement..::.Resources/Application..::.Resources 属性中获取 ResourceDictionary

运行时 Add 调用需要一个键,这满足 ResourceDictionary 中的每个项都有一个键的要求。对于在运行时添加到 ResourceDictionary 的任何内容,您都将无法为可由主对象树的 XAML 命名范围访问的 x:Name 提供值,因为 x:Name 和等效的 Name 在 XAML 中都是只可设置的。尽管您可以先调用 XamlReader..::.Load 来加载包含内部 x:Name / Name 属性的 XAML,然后将创建的对象树作为资源添加,但是这并不能解决主命名范围中的名称问题,因为 Load 始终创建离散的 XAML 命名范围。对于在运行时设置 Name 的限制通常不是问题,但如果您尝试使用演示图板对在运行时添加到资源的对象上的属性进行动画处理,并且需要 TargetName,则此限制可能会成为问题。对于这些情况,仍然可以使用真正的 PropertyPath,通过从树中在主 XAML 命名范围中有可用名称的某个对象启动属性路径,来间接地以属性为目标。

重用资源

在某些情况下,可以将在资源中定义的值赋给多个对象。

  • ResourceDictionary 中定义的模板和样式始终可以重用,因为应用模板或设置样式属性的机制是专为此目的而设计的。

  • 值类型(如字符串)可以使用多次。重用的任何值类型都仅仅被复制。(在对象元素 XAML 用法中包含字符串和其他 System 定义的值类型(以便可以对其进行键控)要求针对 System 和 mscorlib 使用前缀来映射 XML 命名空间;请参见 Silverlight XAML 命名空间以及将 XAML 命名空间映射为前缀。)

  • 资源系统还支持某些对象的内置共享(如果这些对象使用多次)。这些对象如下:

进入可视化树的对象(如任何 UIElement)如果是由 StaticResource 标记扩展引用的,则通常不能从一个资源字典中检索多次,尝试这样做会生成分析器异常。尝试重用对象定义是模板的一个方案,本身不是资源字典。对象定义重用的另一个可能方法是将 XAML 输入用于 XamlReader..::.Load,但对相同的 XAML 输入调用此方法多次将返回多个对象。

generic.xaml

generic.xaml 是一种用于控件的特殊实现技术,通常合并 ResourceDictionary。如果指定了 TargetType 属性,则仅在 generic.xaml 中,Name / x:Namex:Key 对于 Style 元素都是可选的。generic.xaml 特有的另一个方面是:为样式和模板资源设置 TargetType 时支持 {x:Type} 标记扩展。这是为了支持与 WPF 的兼容性和迁移功能,其中 {x:Type} 标记扩展是全局支持的。在 generic.xaml 外部,Silverlight XAML 分析器将隐式转换用于 Type 类型的任何属性,显式使用 {x:Type} 不受支持,会生成分析器错误。有关 generic.xaml 的更多信息,请参见通过创建 ControlTemplate 来创建新的控件

与 WPF 在 ResourceDictionary 实现上的差异

  • 如"键和资源"一节所述,SilverlightResourceDictionary 可以有 x:Name,而不是 x:Key,或者二者兼而有之。除某些与样式和模板有关的显式键情况之外,WPF 始终需要 x:Key

  • Silverlight 不支持 FindResource API(不是严格意义上的 ResourceDictionary 问题,但是与总体用法有关)。

  • Silverlight 不支持 {DynamicResource}。如果要从 WPF 迁移 XAML,则可以将其转换为 {StaticResource},并在 ResourceDictionary 中定义它们,否则必须替换相关引用。同样,这也不是严格意义上的 ResourceDictionary 问题。

  • 在 WPF 中,模板的基类型 (FrameworkTemplate) 还具有一个 Resources 属性。Silverlight 版本的 FrameworkTemplate 不具有 Resources 属性。

  • Silverlight XAML 不支持 x:Shared,也不支持 x:Static。

  • Silverlight 比 WPF 的可共享类型少。WPF 中的某些可共享类型(如 Geometry 派生类型)在 Silverlight 中不可共享。

  • Silverlight 不支持引用 UIElement 作为资源(应用的模板除外,它的概念不同)。WPF 允许引用 UIElement 作为资源,在 WPF XAML 中使用 ResourceDictionary 作为一种重构技术是非常有效的方案,您只需要将该 UIElement 插入对象树一次。

资源字典和本地化

资源字典可以包含要本地化的字符串,这些字符串可以作为 sys:String 对象,也可以作为特定对象的特性字符串值。如果您使用完全基于 ResourceDictionary 的技术来本地化 XAML 中定义的 UI,则通常要求对每个区域设置进行单独编译。因此要为应用程序的每个区域设置生成一个 XAP,并通过在 HTML 或 Silverlight 初始化级别为每个区域设置指定不同来处理这些 XAML 文件的部署分发问题。

在基于 Silverlight 的应用程序中,推荐使用另一种方法来处理 XAML 中的可本地化 UI 字符串,该方法可与用于 Silverlight 的现有 Visual Studio 资源基础结构及项目模板完美集成。此方法依赖于为可本地化字符串创建自定义资源类,并结合 Silverlight 数据绑定和资源字典功能。有关更多信息,请参见本地化基于 Silverlight 的应用程序中的"使 XAML 可本地化"部分。

请参见

参考

ResourceDictionary

其他资源

StaticResource 标记扩展

资源文件

应用程序模型

通过使用 ControlTemplate 自定义现有控件的外观

动画概述

本地化基于 Silverlight 的应用程序

分享到:
评论

相关推荐

    Visual.Basic.2010.&.NET4.高级编程(第6版)-文字版.pdf

    1.2.9 资源 23 1.2.10 设置 24 1.2.11 其他项目属性选项卡 26 1.3 provb_vs2010项目 27 1.3.1 在代码中设置窗体属性 29 1.3.2 visual studio的其他组件 37 1.4 增强示例应用程序的功能 37 1.4.1 定制...

    silverlight多语言的实现

    两种方式实现多语言: 1、通过资源文件的绑定; 2、通过继承新的控件和字典;

    Silverlight2.0功能展示Demo源码

    Silverlight2.0功能展示Demo源码 1、Silverlight(3) - 2.0控件之Border, Button, Calendar, Canvas, CheckBox, ComboBox 介绍 Silverlight 2.0 控件一览:Border, Button, Calendar, Canvas, CheckBox, ComboBox 2...

    silverlight 3 控件经典入门学习案例

    该组件同样提供了附加属性,使资源字典能从外部源加载。层次状样式同样被支持,这与WPF相类似 31.有关Theme(主题): 在Silverlight的开发中,为组件设置统一的主题会让程序的外观显得美观大方 32.有关Expander组件...

    wp7 控件练习

    这两个项目是WP开发的基础控件,页面布局和资源字典的练习 WPControls 是wp基础控件练习 SilverlightToolkitControls 是SilverlightToolkit中的控件练习 1. 项目WPControls中包含如下控件使用: 面板类控件 Grid ...

    在C#中实现ObservableDictionary

    在当前的.NET FRAMEWORK中试没有实现了INotifyCollectionChanged和INotifyPropertyChanged的字典集合,这直接导致了WPF或者SILVERLIGHT中的LISTVIEW等控件不能动态显示集合中的更新。本资源就是实现了这些功能的一个...

    一款非常好的WPF编程宝典2010 源代码

    11.3.8 使用资源字典组织资源 283 11.3.9 在程序集之间共享资源 284 11.4 结束语 287 第12章 样式 288 12.1 样式基础 288 12.1.1 创建样式对象 291 12.1.2 设置属性 292 12.1.3 关联事件处理程序 293 12.1.4...

    Apress.Pro.WPF.in.C.Sharp.2008.2nd.Edition.Feb.2008

    11.3.8 使用资源字典组织资源 283 11.3.9 在程序集之间共享资源 284 11.4 结束语 287 第12章 样式 288 12.1 样式基础 288 12.1.1 创建样式对象 291 12.1.2 设置属性 292 12.1.3 关联事件处理程序 293 12.1.4 多层...

Global site tag (gtag.js) - Google Analytics