UWP入门(六)-- ResourceDictionary 和 XAML 资源引用
原文: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 资源引用的更多相关文章
- ResourceDictionary 和 XAML 资源引用
XAML 定义应用的 UI,并且 XAML 也可以定义 XAML 中的资源.资源通常是对你希望多次使用的某些对象的定义.你要为 XAML 资源定义一个键,以供将来引用,该键的作用类似于资源的名称.你可 ...
- WPF ResourceDictionary XAML资源 c#代码 获取与遍历
使用C#代码来获取XAML资源,除去正常的FindResource.而且是能查询到资源的对象. 说实话还是很麻烦的. 比如说我现在有一堆静态资源放在xaml的资源中,我想通过绑定的方式来获取. 好比是 ...
- UWP入门(四)--设置控件样式
原文:UWP入门(四)--设置控件样式 官方定义:可以使用 XAML 框架通过多种方式自定义应用的外观. 通过样式可以设置控件属性,并重复使用这些设置,以便保持多个控件具有一致的外观. 可分享至不同e ...
- UWP 入门教程2——如何实现自适应用户界面
系列文章 UWP入门教程1——UWP的前世今生 如上文所说的,布局面板根据可用的屏幕空间,指定界面元素的大小和位置.例如StackPanel 会水平或垂直排列界面元素.Grid 布局与CSS 中的表格 ...
- WPF XAML 资源样式模板属性存放位置
WPF的XAML 资源申明 类似HTML. 整体来说分3种1.行类资源样式属性 1.1 行内属性 <Button Content="按钮" Foreground=" ...
- 网络编程懒人入门(六):深入浅出,全面理解HTTP协议
本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...
- DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表
原文:DevExpress XtraReports 入门六 控件以程序方式创建一个 交叉表 报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助 ...
- wpf资源嵌套,一个资源引用另外一个资源,被引用的资源应该声明在前面
在wpf的XAML的Window.Resources中,一个资源引用另外一个资源,出现如下错误: “错误 1 “{DependencyProperty.UnsetValue}”不是 Setter 上“ ...
- Spring Boot入门(六):使用MyBatis访问MySql数据库(注解方式)
本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 本篇博客我们讲解下在Spring Boot中使用MyBatis访问MySql数据库的简单用法. 1.前期 ...
随机推荐
- 学习鸟哥的Linux私房菜笔记(11)——系统监视1
一.了解系统状况 uname:显示系统信息 hostname:显示主机名 last:列出最近的用户登录 lastlog:列出每一个用户的最近登录情况 free:显示内存使用状况 还可以使用vmstat ...
- java中<T> T和T的区别?
如果你希望 getMax 方法的返回值类型为 T,就要这样去定义getMax方法: public T getMax() 如果你希望 getMax 方法返回值的类型由调用者决定,那么就这么去定义 get ...
- View的绘制顺序
1.写在 super.onDraw() 的下面 把绘制代码写在 super.onDraw() 的下面,由于绘制代码会在原有内容绘制结束之后才执行,所以绘制内容就会盖住控件原来的内容. 2.写在 sup ...
- 一个2013届毕业生(踏上IT行业)的迷茫(1)
从毕业到现在已经快半年了,已经想写这篇文字很久了,但是一次又一次的被没有时间给搁置了,今天突然好想写一篇自己这么多年的总结,算是一种反思,也可以看作为未来的人生指路吧. 我和很多搞IT的同行们一样,不 ...
- html head标签的内容跑到body标签中 , 并且body中多了个空格
今天遇到一个奇怪的问题 , 就是在head标签中写的内容跑到body标签中 , 第一种也是经常遇到的情况就是编码 UTF-8 格式带BOM的 , 这种情况是会多一个空格 , 这个基本都知道 , 按ut ...
- WinFrom - 打开一个窗体关闭另一个窗体
在写Winform程序的时候,经常会遇到“打开一个新的窗体然后关闭本窗体”之类的问题.最常见的就是登陆界面和主窗体了.而最常见的处理方法就是表单判断正确后 new MainForm().Show(); ...
- [Scikit-Learn] - introduction
scikit-learn是一个用于机器学习的 Python 模块,建立在SciPy基础之上. 主要特点: 操作简单.高效的数据挖掘和数据分析 无访问限制,在任何情况下可重新使用 建立在NumPy.Sc ...
- 自定义Behavior 实现Listbox自动滚动到选中项
原文:自定义Behavior 实现Listbox自动滚动到选中项 blend为我们提供方便的behavior来扩展我们的控件,写好之后就可以在blend中方便的使用了. 下面是自定义的behavior ...
- 在Microsoft Expression Blend 2 中绘制圆角矩形按钮
原文:在Microsoft Expression Blend 2 中绘制圆角矩形按钮 /* 声明:转载请保留此信息:http://www.BrawDraw.com, http://www.ZPXP.c ...
- XenServer重置存储管理SR至Ext3
Xenserver默认安装到本地磁盘,它是基于本地磁盘上Linux的LVM所管理,在xenserver创建为LVM Typer的本地SR,xenserver在LVM上不支持Thin Provision ...