【WPF.NET开发】WPF中的XAML资源

2024-01-13 15:20
文章标签 开发 资源 net wpf xaml

本文主要是介绍【WPF.NET开发】WPF中的XAML资源,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文内容

  1. 使用 XAML 中的资源
  2. 静态和动态资源
  3. 静态资源
  4. 动态资源
  5. 样式、DataTemplate 和隐式键

资源是可以在应用中的不同位置重复使用的对象。 资源的示例包括画笔和样式。 本概述介绍如何使用 Extensible Application Markup Language (XAML) 中的资源。 你还可以使用代码创建和访问资源。

 备注

本文所述的 XAML 资源与应用资源不同,后者通常指添加到应用中的文件,例如内容、数据或嵌入式文件。

1、使用 XAML 中的资源

下面的示例将 SolidColorBrush 定义为页面根元素上的资源。 该示例随后引用资源,并使用它来设置多个子元素的属性,其中包括 Ellipse、TextBlock 和 Button。

<Page Name="root"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
><Page.Resources><SolidColorBrush x:Key="MyBrush" Color="Gold"/><Style TargetType="Border" x:Key="PageBackground"><Setter Property="Background" Value="Blue"/></Style><Style TargetType="TextBlock" x:Key="TitleText"><Setter Property="Background" Value="Blue"/><Setter Property="DockPanel.Dock" Value="Top"/><Setter Property="FontSize" Value="18"/><Setter Property="Foreground" Value="#4E87D4"/><Setter Property="FontFamily" Value="Trebuchet MS"/><Setter Property="Margin" Value="0,40,10,10"/></Style><Style TargetType="TextBlock" x:Key="Label"><Setter Property="DockPanel.Dock" Value="Right"/><Setter Property="FontSize" Value="8"/><Setter Property="Foreground" Value="{StaticResource MyBrush}"/><Setter Property="FontFamily" Value="Arial"/><Setter Property="FontWeight" Value="Bold"/><Setter Property="Margin" Value="0,3,10,0"/></Style></Page.Resources><StackPanel><Border Style="{StaticResource PageBackground}"><DockPanel><TextBlock Style="{StaticResource TitleText}">Title</TextBlock><TextBlock Style="{StaticResource Label}">Label</TextBlock><TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" /><Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button><Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" /></DockPanel></Border></StackPanel>
</Page>

每个框架级元素(FrameworkElement 或 FrameworkContentElement)都具有 Resources 属性,该属性是包含已定义资源的 ResourceDictionary 类型。 你可以在任何元素上定义资源,例如 Button。 但是,最常在根元素上定义资源,本示例中的根元素为 Page。

资源字典中的每个资源都必须具有唯一键。 在标记中定义资源时,可通过 x:Key 指令来分配唯一键。 通常情况下,这个键是一个字符串;但是,也可使用相应的标记扩展将其设置为其他对象类型。 资源的非字符串键用于 WPF 中的某些功能区,尤其是样式、组件资源和数据样式。

你可以使用具有资源标记扩展语法(指定资源的键名)的已定义资源。 例如,将资源用作另一个元素上的属性的值。

<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>

在前面的示例中,如果 XAML 加载程序处理 Button 上 Background 属性的值 {StaticResource MyBrush},则资源查找逻辑会首先检查 Button 元素的资源字典。 如果 Button 没有资源键 MyBrush 的定义(在该示例中没有;其资源集合为空),则查找逻辑接下来会检查 Button 的父元素,即 Page。 如果在 Page 根元素上定义资源,则 Page 的逻辑树中的所有元素都可以访问它。 而且,你可以重复使用相同的资源来设置接受与该资源所表示类型相同的类型的所有属性的值。 在前面的示例中,同一 MyBrush 资源设置两个不同的属性:Button 的 Background 和 Rectangle 的 Fill。

2、静态和动态资源

资源可引用为静态资源或动态资源。 可通过使用 
StaticResource 标记扩展或 
DynamicResource 标记扩展创建引用。 标记扩展是 XAML 的一项功能,可以通过使用标记扩展来处理属性字符串并将对象返回到 XAML 加载程序,从而指定对象引用。 

使用标记扩展时,通常会以字符串的形式提供一个或多个由该特定标记扩展处理的参数。 
StaticResource 标记扩展通过在所有可用的资源字典中查找键值来处理键。 处理在加载期间进行,即加载过程需要分配属性值时。DynamicResource 标记扩展
则通过创建表达式来处理键,而且表达式会保持未计算状态,直至应用运行为止。当应用实际运行时,表达式会进行计算并提供一个值。

在引用某个资源时,下列注意事项可能会对于使用静态资源引用还是使用动态资源引用产生影响:

  • 确定如何为应用创建资源的整体设计(在每页上、在应用程序中、在宽松的 XAML 中或在仅包含资源的程序集中)时,请考虑以下事项:

  • 应用的功能。 实时更新资源是否为应用要求的一部分?

  • 该资源引用类型的相应查找行为。

  • 特定的属性或资源类型,以及这些类型的本机行为。

3、静态资源

在以下情况下,最适合使用静态资源引用:

  • 应用设计将其大多数资源集中到页面或应用程序级资源字典中。 静态资源引用不基于运行时行为(例如重载页面)重新计算。 因此,根据资源和应用设计,如果避免不必要地使用大量动态资源引用,可能会一定程度地提高性能。

  • 要设置不在 DependencyObject 或 Freezable 上的属性的值。

  • 要创建的资源字典将编译成 DLL,并将打包为应用的一部分或在应用间共享。

  • 要为自定义控件创建主题,并要定义在主题中使用的资源。 在这种情况下,通常不希望执行动态资源引用查找行为,而是希望执行静态资源引用行为,以确保查找可预测并自包含到主题中。 使用动态资源引用时,即使主题中的引用也会在运行时前保持未计算状态。 而且,主题可能会得到应用,但某个本地元素仍会重新定义主题正尝试引用的键,并且该本地元素在查找期间会排在主题之前。 如果发生这种情况,主题的行为将偏离预期方式。

  • 要使用资源设置大量依赖属性。 依赖属性会通过属性系统启用有效值缓存功能;因此,如果为可在加载时进行计算的依赖属性提供了值,则该依赖属性不必检查是否存在重新计算的表达式并可返回最后一个有效值。 此项技术可以提高性能。

  • 想为所有使用者更改基础资源,或想通过使用 x:Shared 属性为每个使用者维护单独的可写实例。

静态资源查找行为

下面介绍属性或元素引用静态资源时自动发生的查找过程:

  1. 查找进程在用于设置属性的元素所定义的资源字典中查找请求的键。

  2. 查找过程随后会向上遍历逻辑树,以查找父元素及其资源字典。 此过程到达根元素后才会停止。

  3. 检查应用资源。 应用资源就是 Application 对象为 WPF 应用定义的资源字典中的资源。

从资源字典中进行的静态资源引用必须引用已在资源引用前进行过词法定义的资源。 静态资源引用无法解析前向引用。 因此,请设计资源字典的结构,以便在每个相应资源字典的开头或邻近开头的位置定义资源。

静态资源查找可以扩展到主题或系统资源中,但此查找受支持只是因为 XAML 加载程序推迟了请求。 为了让页面加载时的运行时主题正确地应用到应用,这种延迟是必需的。 但是,不建议使用对已知仅在主题中存在或作为系统资源存在的键的静态资源引用,因为如果用户实时更改主题,不会重新计算此类引用。 请求主题或系统资源时,动态资源引用更为可靠。 例外情况是当主题元素自身请求另一个资源。 出于上述原因,这些引用应该是静态资源引用。

因找不到静态资源引用而引发的异常行为各不相同。 如果资源被延迟,则异常会在运行时发生。 如果资源未延迟,则异常会在加载时发生。

4、动态资源

在以下情况下,最适合使用动态资源:

  • 资源(包括系统资源或用户可设置的资源)的值取决于直到运行时才知道的条件。 例如,你可以创建 setter 值(引用由 SystemColors、SystemFonts 或 SystemParameters 公开的系统属性)。 这些值是真正的动态值,因为它们最终来自用户和操作系统的运行时环境。 或许还拥有可能会发生变化的应用程序级主题,而页面级资源访问也必须捕获其中的变化。

  • 要为自定义控件创建或引用主题样式。

  • 打算在应用生存期内调整 ResourceDictionary 的内容。

  • 拥有存在相互依赖关系且可能需要进行前向引用的复杂资源结构。 静态资源引用不支持前向引用,但动态资源引用支持,因为资源在运行时之前不需要计算,所以前向引用是一个不相关的概念。

  • 要引用从编译或工作集的角度来看很大的资源,而且该资源在页面加载时可能不会立即使用。 页面加载时,始终会从 XAML 加载静态资源引用。 但是,动态资源引用在使用前不会加载。

  • 要创建的样式的 setter 值可能来自受主题或其他用户设置影响的其他值。

  • 要将资源应用于可能会在应用生存期内在逻辑树中重定父级的元素。 父级更改后,资源查找范围也可能会随之更改;因此,如果希望重定父级的元素的资源基于新范围重新进行计算,请始终使用动态资源引用。

动态资源查找行为

如果调用 FindResource 或 SetResourceReference,则动态资源引用的资源查找行为会与代码中的查找行为并行执行:

  1. 查找在用于设置属性的元素所定义的资源字典中查找请求的键:

    • 如果元素定义 Style 属性,则该元素的 System.Windows.FrameworkElement.Style 将检查其 Resources 字典。

    • 如果元素定义 Template 属性,则检查该元素的 System.Windows.FrameworkTemplate.Resources 字典。

  2. 查找会向上遍历逻辑树,以查找父元素及其资源字典。 此过程到达根元素后才会停止。

  3. 检查应用资源。 应用资源就是 Application 对象为 WPF 应用定义的资源字典中的资源。

  4. 检查主题资源字典中当前处于活动状态的主题。 如果主题在运行时发生更改,则会重新计算值。

  5. 检查系统资源。

异常行为(如果有)各不相同:

  • 如果 FindResource 调用请求了某个资源但未找到该资源,则会引发异常。

  • 如果 TryFindResource 调用请求了某个资源但未找到该资源,不会引发任何异常,并且返回的值为 null。 如果要设置的属性不接受 null,则仍有可能引发更深的异常(取决于要设置的单独属性)。

  • 如果 XAML 中的动态资源引用请求了某个资源但未找到该资源,则行为取决于常规属性系统。 常规行为即存在资源的级别上没有发生属性设置操作时执行的行为。 例如,如果尝试使用无法计算的资源来设置个别按钮元素上的背景,则值设置操作不会产生任何结果,但有效值可能仍来自属性系统和值优先级中的其他参与者。 例如,背景值可能仍来自在本地定义的某个按钮样式,或来自主题样式。 对于并非由主题样式定义的属性,资源计算失败后的有效值可能来自属性元数据中的默认值。

限制

动态资源引用存在一些重要限制。 必须至少满足以下条件之一:

  • 要设置的属性必须是 FrameworkElement 或 FrameworkContentElement 上的属性。 该属性必须由 DependencyProperty 支持。

  • 该引用用于 StyleSetter 内的值。

  • 要设置的属性必须是 Freezable(以 FrameworkElement 或 FrameworkContentElement 属性的值或 Setter 值的形式提供)上的属性。

由于要设置的属性必须是 DependencyProperty 或 Freezable 属性,大多数属性更改都可以传播到 UI,这是因为属性更改(更改的动态资源值)会经由属性系统确认。 大多数控件都包含相应的逻辑;当 DependencyProperty 有所更改且该属性可能会影响布局时,该逻辑将强制使用控件的其他布局。 但是,并不保证所有使用 DynamicResource 标记扩展作为其值的属性都能在 UI 中提供实时更新。 此功能可能仍会因属性、属性所属的类型,甚至应用的逻辑结构而异。

5、样式、DataTemplate 和隐式键

尽管 ResourceDictionary 中的所有项都必须具有键,但这并不意味着所有资源都必须具有显式 x:Key。 多种对象类型在定义为资源时都支持隐式键,其键值会与另一属性的值绑定。 这类键被称为隐式键,而 x:Key 属性为显式键。 任何隐式键都可通过指定显式键来覆盖。

关于资源,一个重要的方案就是用于定义 Style。 事实上,Style 几乎总会作为资源字典中的条目进行定义,因为样式在本质上可供重复使用。 

控件样式可通过隐式键来创建和引用。 用于定义控件默认外观的主题样式依赖于该隐式键。 从请求的角度来看,隐式键是控件本身的 Type。 从定义资源的角度来看,隐式键是样式的 TargetType。 因此,如果要创建自定义控件的主题或要创建会与现有主题样式交互的样式,则无需为该 Style 指定 x:Key 指令。 另外,如果想要使用主题样式,则根本无需指定任何样式。 例如,即使 Style 资源似乎没有键,以下样式定义仍起作用:

<Style TargetType="Button"><Setter Property="Background"><Setter.Value><LinearGradientBrush><GradientStop Offset="0.0" Color="AliceBlue"/><GradientStop Offset="1.0" Color="Salmon"/>           </LinearGradientBrush></Setter.Value></Setter>  <Setter Property="FontSize" Value="18"/>
</Style>

该样式确实具有一个键:隐式键 typeof(System.Windows.Controls.Button)。 在标记中,可以直接将 TargetType 指定为类型名称(或者,可以选择使用 {x:Type...},以返回 Type。

通过 WPF 使用的默认主题样式机制,即使 Button 本身不尝试指定其 Style 属性或对样式的特定资源引用,该样式也将作为页面上 Button 的运行时样式应用。 在页面中定义的样式位于查找序列中的靠前位置(在主题字典样式之前),其所用的键与主题字典样式的键相同。 可以在页面上的任意位置指定 <Button>Hello</Button>,使用 Button 的 TargetType 定义的样式将应用于该按钮。 如果需要,仍可为此样式显式指定与 TargetType 的类型值相同的键,以求在标记中清楚明示,但这是可选的。

如果 OverridesDefaultStyle 为 true,则样式的隐式键不会应用于控件。 (另请注意,OverridesDefaultStyle 可能被设置为控件类的本机行为的一部分,而不是在控件的实例上显式设置。)此外,为了支持在派生类方案中使用隐式键,控件必须替代 DefaultStyleKey(作为 WPF 的一部分提供的所有现有控件都包括此替代)。

DataTemplate 也有一个隐式键。 DataTemplate 的隐式键是 DataType 属性值。 DataType 也可以作为类型的名称来指定,而不是使用 {x:Type...} 来显式指定。

这篇关于【WPF.NET开发】WPF中的XAML资源的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/601912

相关文章

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD