原文:UWP入门(六)-- ResourceDictionary 和 XAML 资源引用

你最希望声明为 XAML 资源的 XAML 元素包括 Style、ControlTemplate、动画组件和 Brush 子类。 我们在此处介绍

  • 如何定义 ResourceDictionary 和键控资源

  • XAML 资源与你定义为应用或应用包一部分的其他资源有何关系

  • 资源字典高级功能
    • MergedDictionaries
    • ThemeDictionaries。

1. 定义和使用 XAML 资源

<Page
x:Class="SpiderMSDN.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Page.Resources>
<SolidColorBrush x:Key="myFavoriteColor" Color="green"/>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources> <TextBlock Foreground="{StaticResource myFavoriteColor}" Text="{StaticResource greeting}" VerticalAlignment="Top"/>
<Button Foreground="{StaticResource myFavoriteColor}" Content="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

所有资源都需要有一个键。 通常,键是通过 x:Key="myString" 定义的字符串。 但是,还有几种其他方法可指定键:

  • 如果未指定 x:Key,则 Style 和 ControlTemplate 需要 TargetType,并且将 TargetType 用作键。 在这种情况下,键是实际的 Type 对象,而非字符串。

  • 如果未指定 x:Key,具有 TargetType 的 DataTemplate 资源会将 TargetType 用作键。 在这种情况下,键是实际的 Type 对象,而非字符串。

  • x:Name 可以代替 x:Key 使用。 但是,x:Name 还会为资源生成代码隐藏字段。 因此,x:Name 的效率低于 x:Key,因为该字段需要在页面加载时进行初始化

StaticResource 标记扩展可以仅使用字符串名称(x:Key 或 x:Name)检索资源。 但是,XAML 框架在决定为尚未设置 Style 和 ContentTemplate 或 ItemTemplate 属性的控件使用哪个样式和模板时,还将查找隐式样式资源(使用 TargetType 而非 x:Key 或 x:Name 的资源)。

此处的 Style 具有隐式键 typeof(Button),并且由于页面底部的 Button 未指定 Style 属性,它将查找具有 typeof(Button) 键的样式:

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Page.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="red"/>
</Style>
</Page.Resources>
<!-- This button will have a red background. -->
<Button Content="Button" Height="100" VerticalAlignment="Center" Width="100"/>
</Page>

2. 查找代码中的资源

像任何其他字典一样,访问资源字典的成员

注意 当你执行在代码中查找资源的操作时,仅找到 Page.Resources 字典中的资源。 与 StaticResource 标记扩展不同,如果未在第一个字典中找到这些资源,该代码不会回退到 Application.Resources 字典

此示例演示如何在页面的资源字典中检索出 redButtonStyle 资源

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Page.Resources>
<Style TargetType="Button" x:Key="redButtonStyle">
<Setter Property="Background" Value="red"/>
</Style>
</Page.Resources>
</Page>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Style redButtonStyle = (Style)this.Resources["redButtonStyle"];
}
}

若要在代码中查找应用范围的资源,请使用 Application.Current.Resources 获取应用的资源目录,如下所示

<Application
x:Class="MSDNSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SpiderMSDN">
<Application.Resources>
<Style TargetType="Button" x:Key="appButtonStyle">
<Setter Property="Background" Value="red"/>
</Style>
</Application.Resources> </Application>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
Style appButtonStyle = (Style)Application.Current.Resources["appButtonStyle"];
}
}

以下是在执行此操作时要记住的两个事项:

  • 第一,在任何页面尝试使用资源时,你需要先添加资源。
  • 第二,不能在应用的构造函数中添加资源

如果在 Application.OnLaunched 方法中添加资源,可以避免这两个问题,如下所示

// App.xaml.cs

sealed partial class App : Application
{
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
SolidColorBrush brush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 0, 255, 0)); // green
this.Resources["brush"] = brush;
// … Other code that VS generates for you …
}
}
}

3.每个 FrameworkElement 都可以具有 ResourceDictionary

FrameworkElement 是控件所继承的基类,并且具有 Resources 属性。 因此你可以将本地资源字典添加到任何 FrameworkElement

此时,资源字典已添加到页面元素

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Page.Resources>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources> <Border>
<Border.Resources>
<x:String x:Key="greeting">Hola mundo</x:String>
</Border.Resources>
<TextBlock Text="{StaticResource greeting}" Foreground="Gray" VerticalAlignment="Center"/>
</Border>
</Page>

此时,Page 和 Border 都具有资源字典,并且都具有名为“greeting”的资源。 TextBlock 位于 Border 内,因此其资源查找将依次查找 Border 的资源、Page 的资源以及 Application 资源。 TextBlock 将读取“Hola mundo”

若要从代码访问元素的资源,请使用该元素的 Resources 属性。 在代码(而非 XAML)中访问 FrameworkElement 的资源,将仅在该字典中查找,而不在父级元素的字典中查找

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Page.Resources>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources> <Border x:Name="border">
<Border.Resources>
<x:String x:Key="greeting">Hola mundo</x:String>
</Border.Resources>
</Border>
</Page>
    public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
string str = (string)border.Resources["greeting"];
}
}

4. 合并的资源字典(上一篇也有,简化版)

合并的资源字典将一个资源字典合并到通常在其他文件中的另一个字典

提示 可以在 Microsoft Visual Studio 中创建资源字典文件,方法是在项目菜单中依次使用add > new item…> dictionary recourse

此时,可以在名为 Dictionary1.xaml 的单独 XAML 文件中定义资源字典

<!-- Dictionary1.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample"> <SolidColorBrush x:Key="brush" Color="Red"/> </ResourceDictionary>

若要使用该字典,请将它与页面的字典合并:

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries> <x:String x:Key="greeting">Hello world</x:String> </ResourceDictionary>
</Page.Resources> <TextBlock Foreground="{StaticResource brush}" Text="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

下面是本示例中会出现的结果。 在 <Page.Resources> 中,声明 <ResourceDictionary>。 当你向 <Page.Resources> 添加资源时,XAML 框架将为你隐式创建资源字典;但是在这种情况下,你需要的不仅是任一资源字典,你还需要包含合并字典的资源字典。

因此请声明 <ResourceDictionary>,然后将内容添加到其 <ResourceDictionary.MergedDictionaries> 集合。 其中每个条目都采用 <ResourceDictionary Source="Dictionary1.xaml"/> 形式。 若要添加多个字典,只需在第一个条目后添加 <ResourceDictionary Source="Dictionary2.xaml"/> 条目即可

<ResourceDictionary.MergedDictionaries>…</ResourceDictionary.MergedDictionaries> 后,你可以选择在主字典中放置其他资源。 你可以使用要合并到的字典中的资源,如同使用常规字典一样。 在上述示例中,{StaticResource brush} 在子级/合并字典 (Dictionary1.xaml) 中查找资源,而 {StaticResource greeting} 在主页字典中查找其资源

在资源查找序列中,仅在检查 ResourceDictionary 的所有其他键控资源后,才会检查 MergedDictionaries 字典。 搜索该级别后,查找会深入到合并后的字典,且对 MergedDictionaries 中的每一项进行检查。 如果存在多个合并的字典,会按在 MergedDictionaries 属性中声明这些字典的顺序的相反顺序来检查它们。 在以下示例中,如果 Dictionary2.xaml 和 Dictionary1.xaml 声明同一个键,则首先使用来自 Dictionary2.xaml 中的键,因为它排在 MergedDictionaries 集的末尾

在任一 ResourceDictionary 范围内,均会检查字典中键的唯一性。 但是,这一范围不会扩展到不同 MergedDictionaries 文件中的不同项

可以结合使用查找序列和跨合并字典范围不强制使用唯一键来创建 ResourceDictionary 资源的回退值序列。 例如,你可能会使用与应用的状态数据和用户首选项数据同步的资源词典,为序列中最后合并的资源字典中的特殊画笔颜色存储用户首选项。 但是,如果尚不存在任何用户首选项,则可为初始 MergedDictionaries 文件中的 ResourceDictionary 资源定义相同的键字符串,并可将其用作回退值。

请记住,始终会在检查合并字典之前检查你在主要资源字典中提供的任何值,所以如果希望使用回退技术,则不要在主要资源字典中定义该资源

5.主题资源和主题字典

ThemeResource 类似于 StaticResource,但资源查找会在主题更改时进行重新评估。

在此示例中,将 TextBlock 的前景设置为当前主题中的值

<TextBlock Text="hello world" Foreground="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" VerticalAlignment="Center"/>

主题字典是一种特殊类型的合并字典,用于保存各种资源,具体资源取决于用户当前在其设备上使用的主题。 例如,“浅色”主题可能使用白色画笔,而“深色”主题可能使用黑色画笔。 画笔会更改它所溶入的资源,但使用该画笔作为资源的控件的组成可能保持不变。 若要在个人模板或样式中重现主题切换行为而不将 MergedDictionaries 用作属性以将项目合并到主词典中,请使用 ThemeDictionaries 属性

ThemeDictionaries 内的每个 ResourceDictionary 元素必须具有一个 x:Key 值。 该值是一个字符串,它为相关主题命名,例如 “Default”、“Dark”、“Light”或“HighContrast”。 通常,Dictionary1 和 Dictionary2 将定义名称相同但值不同的资源。

在此处,将红色文本用于浅色主题,蓝色文本用于深色主题

<!-- Dictionary1.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample"> <SolidColorBrush x:Key="brush" Color="Red"/> </ResourceDictionary> <!—Dictionary2.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample"> <SolidColorBrush x:Key="brush" Color="blue"/> </ResourceDictionary>

在此示例中,将 TextBlock 的前景设置为当前主题中的值

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" x:Key="Light"/>
<ResourceDictionary Source="Dictionary2.xaml" x:Key="Dark"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>
<TextBlock Foreground="{StaticResource brush}" Text="hello world" VerticalAlignment="Center"/>
</Page>

对于主题字典,每当使用 ThemeResource 标记扩展进行引用并且系统检测到主题更改时,要用于资源查找的活动字典都会动态更改。 系统执行的查找行为基于将活动主题映射到特定主题字典的 x:Key 操作

检查主题字典在默认 XAML 设计资源中的构建方式十分有用,这些资源与 Windows 运行时默认用作其控件的模板相对应。 使用文本编辑器或 IDE 打开 \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic 中 的 XAML 文件。 请注意主题字典首先在 generic.xaml 中的定义方式,以及每个主题字典定义相同键的方式。 然后每个这样的键由构成各种键控元素的元素所引用,这些键控元素位于主题字典外部并且稍后在 XAML 中定义。 还存在用于设计的单独 themeresources.xaml 文件,该文件仅包含主题资源和额外模板,不包含默认控件模板。 这些主题区域是你将在 generic.xaml 中看到的内容副本。

当你使用 XAML 设计工具以编辑样式和模板的副本时,设计工具会提取 XAML 设计资源词典中的片段并将其作为应用和项目一部分的 XAML 字典元素的本地副本放置。

有关可用于应用的特定于主题的资源和系统资源的详细信息和列表,请参阅 XAML 主题资源

UWP入门(六)-- ResourceDictionary 和 XAML 资源引用的更多相关文章

  1. ResourceDictionary 和 XAML 资源引用

    XAML 定义应用的 UI,并且 XAML 也可以定义 XAML 中的资源.资源通常是对你希望多次使用的某些对象的定义.你要为 XAML 资源定义一个键,以供将来引用,该键的作用类似于资源的名称.你可 ...

  2. WPF ResourceDictionary XAML资源 c#代码 获取与遍历

    使用C#代码来获取XAML资源,除去正常的FindResource.而且是能查询到资源的对象. 说实话还是很麻烦的. 比如说我现在有一堆静态资源放在xaml的资源中,我想通过绑定的方式来获取. 好比是 ...

  3. UWP入门(四)--设置控件样式

    原文:UWP入门(四)--设置控件样式 官方定义:可以使用 XAML 框架通过多种方式自定义应用的外观. 通过样式可以设置控件属性,并重复使用这些设置,以便保持多个控件具有一致的外观. 可分享至不同e ...

  4. UWP 入门教程2——如何实现自适应用户界面

    系列文章 UWP入门教程1——UWP的前世今生 如上文所说的,布局面板根据可用的屏幕空间,指定界面元素的大小和位置.例如StackPanel 会水平或垂直排列界面元素.Grid 布局与CSS 中的表格 ...

  5. WPF XAML 资源样式模板属性存放位置

    WPF的XAML 资源申明 类似HTML. 整体来说分3种1.行类资源样式属性 1.1 行内属性 <Button Content="按钮" Foreground=" ...

  6. 网络编程懒人入门(六):深入浅出,全面理解HTTP协议

    本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...

  7. DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表

    原文:DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助 ...

  8. wpf资源嵌套,一个资源引用另外一个资源,被引用的资源应该声明在前面

    在wpf的XAML的Window.Resources中,一个资源引用另外一个资源,出现如下错误: “错误 1 “{DependencyProperty.UnsetValue}”不是 Setter 上“ ...

  9. Spring Boot入门(六):使用MyBatis访问MySql数据库(注解方式)

    本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 本篇博客我们讲解下在Spring Boot中使用MyBatis访问MySql数据库的简单用法. 1.前期 ...

随机推荐

  1. 手机端自适应布局demo

    原型如下: 要求如下:适应各种机型 源码如下: <!DOCTYPE html > <html>     <head>         <meta http-e ...

  2. 关于用什么作为dll版本号的思考

    作者:朱金灿 来源:http://blog.csdn.net/clever101 一个软件模块的版本如何维护呢?毫无疑问,它需要一个版本号.通过比对版本号就知道哪个高版本,哪个是低版本了.软件模块以d ...

  3. NOIP模拟 - 莫队

    题目描述 给定一个元素个数为 n 的整数数组 a 和 Q 个问题,每个问题有 x,y 两个参数,请统计共有多少个整数 K 满足 K 在 a[x]-a[y] 中出现了恰好 K 次. 输入格式 第一行两个 ...

  4. css中背景 字体 文体属性练习

    @charset "utf-8"; body{ background-color:#332244;/*//背景颜色*/ background-image:("../kk. ...

  5. 手机预览微信小程序

    1. 获取微信小程序的 AppID 登录 https://mp.weixin.qq.com ,就可以在网站的“设置”-“开发者设置”中,查看到微信小程序的 AppID 了,注意不可直接使用服务号或订阅 ...

  6. JEECG 什么是商业版本的功能最近添加的好友?

    JEECG 商业版本号近期新增什么功能啦? 2014-12-18 JEECG JEECG jeecg添加新的功能啦! !. 1.流程设计器 2.集成工作流引擎activit,智能化封装,在线配置表单, ...

  7. 在Windows中安装MinGW-w64(有图,一步一步)

    在Windows中安装MinGW-w64 发表回复 如需配合Sublime Text 3编译C程序, 请参考本站文章: 使用Sublime Text 3与MinGW-w64编译C语言程序 MinGW, ...

  8. Distinct去除重复项

    之前在做权限模块时,因不同角色可能拥有相同的菜单,导致呈现在浏览器上时出现重复菜单项,所以需要在获取用户拥有菜单项时需要过滤重复项, 用到了Distinct,两个重载 public static IQ ...

  9. WPF 将图片进行灰度处理

    原文:WPF 将图片进行灰度处理 处理前:      处理后:   这个功能使用使用了 FormatConvertedBitmap(为BitmapSource提供像素格式转换功能)   代码如下:   ...

  10. 【C++智能指针 auto_ptr】

    <More Effective C++>ITEM M9他提到auto_ptr.说是当异常产生的时候.怎么释放为对象分配的堆内存,避免反复编写内存释放语句. PS:这里书里面提到函数退出问题 ...