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

news/2024/2/29 16:48:38/文章来源:https://blog.csdn.net/m0_51887793/article/details/135542744

本文内容

  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...} 来显式指定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_925734.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP面试小结(20240108)

PHP 部分 1. php的包管理工具是如何实现自动加载的 换句话问&#xff1a;composer 实现原理是什么&#xff1f;spl_autoload_register() 首先&#xff0c;Composer 是 PHP 的一个包管理和包依赖管理的工具 &#xff0c; 打开安装之后生成的 "vendor" 文件, 里面有个…

opencv_角点检测

文章内容 一个opencv检测角点的程序 运行效果 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream>using namespace cv; using namespace std;void detectCorners(M…

uniapp中按钮点击跳转页面失效,纠正错误(亲测可用)

不知道伙伴你的错误和我是否一致&#xff1f; 我当时为了点击跳转按钮发现跳转不了&#xff0c;如下错误提示&#xff1a; worker.js?libNameWAAccelerateWorker.js:1 [Deprecation] SharedArrayBuffer will require cross-origin isolation as of M92, around July 2021. S…

Debian12 安装jenkins 公钥配置

jenkins公钥配置 参考&#xff1a;Debian Jenkins 软件包 这是 Jenkins 的 Debian 软件包存储库&#xff0c;用于自动安装和升级。 要使用此存储库&#xff0c;请先将密钥添加到您的系统&#xff08;对于每周发布行&#xff09;&#xff1a; sudo wget -O /usr/share/keyring…

36.有效的数独

36.有效的数独 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图…

企业微信开发:自建应用:access_token

access_token 过期后接口响应 access_token 已经过期&#xff08;2小时&#xff09;后&#xff0c;调用接口的响应&#xff1b;本文中以发送消息接口为例&#xff0c;说明接口响应的情况。 官方开发文档链接&#xff1a;获取access_token access_token 过期后调用接口 响应体 …

2024年腾讯云主机价格表,附报价明细

腾讯云服务器租用价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月&#xff0c;云服务器CVM S5实例2核2G配置280.8元一年…

机器学习小记——KNN(K近邻)

为了让绝大多数人都可以看懂&#xff0c;所以我就用简单的话语来讲解机器学习每一个算法 第一次写ML的博文&#xff0c;所以可能会有些地方出错&#xff0c;欢迎各位大佬提出意见或错误 祝大家开心进步每一天&#xff5e; 博文代码全部为python 简单的说一下什么是机器学习…

adb wifi 远程调试 安卓手机 命令

使用adb wifi 模式调试需要满足以下前提条件&#xff1a; 手机 和 PC 需要在同一局域网下。手机需要开启开发者模式&#xff0c;然后打开 USB 调试模式。 具体操作步骤如下&#xff1a; 将安卓手机通过 USB 线连接到 PC。&#xff08;连接的时候&#xff0c;会弹出请求&#x…

Android 系统启动过程纪要(基于Android 10)

前言 看过源码的都知道&#xff0c;Launcher系统启动都会经过这三个进程 init ->zygote -> system_server。今天我们就来讲解一下这三个进程以及Launcher系统启动。 init进程 准备Android虚拟机环境&#xff1a;创建和挂载系统文件目录&#xff1b;初始化属性服务&…

AI大模型预先学习笔记二:prompt提问大模型、langchain使用大模型框架、fine tune微调大模型

文章目录 一、Prompt Engineering&#xff08;怎么去提问大模型&#xff09;1&#xff09;环境准备2&#xff09;交互代码的参数备注3&#xff09;交互代码 二、LangChain&#xff08;一个框架去使用大模型&#xff09;1&#xff09;LangChain核心介绍&#xff1a;I/O模块、数据…

Java NIO (二)NIO Buffer类的重要方法

1 allocate()方法 在使用Buffer实例前&#xff0c;我们需要先获取Buffer子类的实例对象&#xff0c;并且分配内存空间。需要获取一个Buffer实例对象时&#xff0c;并不是使用子类的构造器来创建&#xff0c;而是调用子类的allocate()方法。 public class AllocateTest {static…

四、Sharding-JDBC系列04:分库分表后,如何不停机迁移数据?

目录 停机迁移方案 双写迁移方案 一般会有两种方案&#xff1a; 停机迁移方案 这种方案最简单也是最low的。 数据迁移前&#xff0c;在网站或者app挂个公告&#xff0c;说0点到早上6点系统进行维护&#xff0c;无法访问。 接着到0点停机&#xff0c;系统停掉&#xff0c;…

k8s---配置资源管理

目录 配置资源管理的方式 secret pod如何来引用secret&#xff1f;&#xff1f;&#xff1f; 陈述式创建&#xff1a; 声明式创建 Secret创建加密文件 使用token挂载 环境变量使用 docker-registry ConfigMap 陈述式 热更新 总结&#xff1a; 配置资源管理的方式 …

Go-gin-example 第二部分 jwt验证

文章目录 使用 JWT 进行身份校验jwt知识点补充认识JWTTOKEN是什么jwt的使用场景jwt的组成headerpayloadsignature 下载依赖包编写 jwt 工具包jwt中间件编写如何获取token 编写获取token的Apimodels逻辑编写路由逻辑编写修改路由逻辑 验证token将中间件接入Gin功能验证模块 续接…

【开源】基于JAVA语言的固始鹅块销售系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固始鹅块模块2.4 鹅块订单模块2.5 评论管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 鹅块类型表3.2.2 鹅块表3.2.3 鹅块订单表3.2.4 鹅块评论表 四、系统展示五、核心代码5.…

FPGA之初探

FPGA的构成 基本逻辑单元CLB CLB是FPGA的基本逻辑单元&#xff0c; 一个 CLB 包括了 2 个 Slices&#xff0c;所以知道Slices的数量就可以知道FPGA的“大概”逻辑资源容量了。一个 Slice 等于 4 个6输入LUT8个触发器(flip-flop)算数运算逻辑&#xff0c;每个 Slice 的 4 个触发…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-17 串讲

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-17 串讲

Komodor:Kubernetes 监控工具全面指南

为了方便起见&#xff0c;Komodor 提供了一个简单的 Web 界面&#xff0c;以帮助您监控 Kubernetes 集群的状态。它拥有付费和免费增值计划&#xff0c;除了在出现问题时通知用户外&#xff0c;还拥有一系列方便的工具&#xff0c;用于跟踪和管理集群中部署的资源的状态。让我们…

如何用GPT进行论文润色与改写?

详情点击链接&#xff1a;如何用GPT进行论文润色与改写&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定…