宇宙很大,生活更大,也许以后还有缘相见。 --三体

该篇作为[WPF 入门笔记 - 04 - 数据绑定] - Additional Content 章节的补充内容

前言

WPF中的每一个元素都有一个Resources属性,该属性存储了一个资源字典集合。一般来说,可以把WPF的资源按照不同的性质分为两种 - 程序集资源(Assembly Resources)和逻辑资源(Logical Resources):

  1. 程序集资源(Assembly Resources)或二进制资源(Binary Resources): MSDN称其为应用资源,这些资源通常是嵌入在应用程序的程序集中的文件,例如图像、音频、视频等。它们被视为应用程序的一部分,并且在运行时作为二进制数据进行访问。可以使用Pack URIRelative URI来引用这些资源。
  2. 逻辑资源(Logical Resources)或对象资源(Object Resources): MSDN称其为XAML 资源,这些资源是在XAML中定义的,用于表示控件样式、模板、数据对象等。它们通过键值对的形式进行定义,并在应用程序中以逻辑方式进行引用和使用。逻辑资源可以在XAML或代码中进行定义,并且可以在整个应用程序中进行共享和重用。[ 尽管可以在代码中创建和操作资源,但通常在XAML中定义 ]

应用资源

又称程序集资源或二进制资源,是指嵌入在应用程序的程序集中的文件或数据。这些资源在编译时被包含在应用程序的可执行文件或程序集中,并以二进制形式存储。以图片为例,假设在Image文件夹下有张名为test.jpg的图片:

访问位于项目文件夹中的图片文件的写法有很多,写几个我会的:

<Window x:Class="WPFDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDemo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="730"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid>
<StackPanel>
<Image Name="Image1" Height="150" Source="E:\WPF\WPFDemo\WPFDemo\Image\test.jpg" />
<Image Name="Image2" Source="Image/test.jpg" />
<Image Name="Image3" Height="150" Source="pack://application:,,,/image/test.jpg" />
</StackPanel>
</Grid>
</Window>

从上到下 - Image1:绝对路径 - Image2:相对路径 - Image3:将图片文件添加到项目的资源文件夹中,然后使用Pack URI来引用程序集资源,还有其他的大家自己研究吧:

XAML 资源

又称逻辑资源,它是一些保存在元素Resources属性中的.NET对象,可以是各种类型的对象,如颜色、样式、数据模板、控件等也可以是一般的.NET对象,可以通过键(Key)来标识资源,以StaticResource或者DynamicResource的方式来引用资源,具体取决于相应的应用场景。

<Window x:Class="WPFDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDemo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Title="MainWindow"
Width="800"
Height="450"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<SolidColorBrush x:Key="BrushColor" Color="OrangeRed" />
<system:String x:Key="MyStringResource">Hello, WPF!</system:String>
</Window.Resources>
<Grid>
<StackPanel>
<Button BorderBrush="{DynamicResource BrushColor}" BorderThickness="3" Content="在Button内定义资源">
<Button.Resources>
<SolidColorBrush x:Key="BrushColor" Color="HotPink" />
</Button.Resources>
</Button>
<Button Margin="5" BorderBrush="{StaticResource BrushColor}" BorderThickness="3"
Content="在窗体内定义资源" />
<TextBlock HorizontalAlignment="Center" FontSize="15" Text="{StaticResource MyStringResource}" />
</StackPanel>
</Grid>
</Window>

Button内定义资源时,应该使用DynamicResource来引用资源。

资源分级

资源可以按照不同的级别进行分级,例如:

系统资源,一般会在app.xaml中集成:

窗体资源,上面例子中的Window.Resources:

控件资源,上面例子中的Button.Resources:

......

静态资源和动态资源

静态资源(StaticResource)和动态资源(DynamicResource)是 WPF 中用于资源绑定的两种不同方式。

  1. 静态资源(StaticResource):

    • 静态资源是在 XAML 中定义并在编译时解析的。
    • 一旦静态资源被解析并应用于目标元素,它们的值将保持不变,不会随后续的资源更改而自动更新。
    • 静态资源适用于在应用程序的生命周期内保持不变的资源,如样式、模板、图像等。
    • 由于静态资源在解析时进行了性能优化,因此在性能要求较高的情况下,静态资源是一个更好的选择。
  2. 动态资源(DynamicResource):
    • 动态资源是在运行时进行解析和更新的。
    • 动态资源允许在应用程序运行时更改资源的值,并自动更新所有使用该资源的目标元素。
    • 动态资源适用于需要动态更改的资源,如主题、样式、语言切换等。
    • 由于动态资源需要在运行时进行解析和更新,因此在性能方面可能会比静态资源稍差。

写个示例看一下具体区别:

<Window x:Class="WPFDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFDemo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources>
<SolidColorBrush x:Key="BrushColor" Color="HotPink" />
</Window.Resources>
<Grid>
<StackPanel>
<Button Margin="5"
BorderBrush="{StaticResource BrushColor}"
BorderThickness="3"
Content="静态资源" />
<Button Margin="5" Click="Button_Click" Content="修改边框颜色" />
<Button Margin="5"
BorderBrush="{DynamicResource BrushColor}"
BorderThickness="3"
Content="动态资源" />
</StackPanel>
</Grid>
</Window>

两个按钮,分别使用静态资源和动态资源的方法设置边框颜色,通过点击事件修改资源中的边框颜色:

private void Button_Click(object sender, RoutedEventArgs e)
{
SolidColorBrush colorBrush = new SolidColorBrush(Colors.BlueViolet);
this.Resources["BrushColor"] = colorBrush;
}

运行程序你会发现,点击修改边框颜色按钮后,之后使用动态资源的按钮才会对资源的变动做出反应:

由此可以大致知道两者的应用场景:

  • 静态资源适用于在应用程序启动时确定并保持不变的资源。例如,全局样式、应用程序图标等。
  • 动态资源适用于需要根据用户交互或其他条件动态更改的资源。例如,切换主题、更改语言、动态样式等。

资源字典

资源字典(Resource Dictionary):一种用于组织和管理资源的集合。

在前面中有提到,每个Resources属性存储着一个资源字典集合。如果希望在多个项目之间共享资源的话,就可以使用资源字典。使用资源字典可以将资源集中管理,提高代码的可维护性和重用性。

创建资源字典就很简单了,Ctrl + Shift + A:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="DefaultButtonStyle" TargetType="Button">
<Setter Property="Margin" Value="5" />
<Setter Property="BorderBrush" Value="HotPink" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Content" Value="Otto" />
<Setter Property="FontSize" Value="12" />
</Style>
</ResourceDictionary>

想要使用这个资源字典的话,首先需要将其合并到应用程序中资源集合位置,当然你也可以合并到窗口资源集合中,但是通常是合并到应用程序资源集合中,因为资源字典的目的就是在于多个窗体中共享,具体的XAML代码如下所示:

<Application x:Class="SwitchThemeDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SwitchThemeDemo"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DictionaryButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

回到页面我们声明几个使用DictionaryButtonStyle.xaml中样式的按钮:

<Window x:Class="SwitchThemeDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SwitchThemeDemo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid>
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}"/>
<Button Style="{StaticResource DefaultButtonStyle}"/>
<Button Style="{StaticResource DefaultButtonStyle}"/>
<Button Style="{StaticResource DefaultButtonStyle}"/>
</StackPanel>
</Grid>
</Window>

可以看到几个按钮都是和样式里定义是一样的,同时在别的窗口或者页面也是可以使用字典中的样式的。

由此可见,资源字典是一种强大的工具,可以帮助管理和组织应用程序中的各种资源,提高代码的可重用性、可维护性和一致性,同时还允许动态更新和定制化。使用资源字典具有以下好处:

  1. 代码重用:资源字典允许在应用程序的多个地方定义和使用相同的资源。这样可以避免重复编写相同的代码,提高代码的重用性和可维护性。
  2. 统一的外观和样式:通过将样式、模板、颜色和其他外观相关的资源放在资源字典中,可以轻松地对整个应用程序的外观进行统一和集中管理。这样可以确保应用程序的各个部分都具有一致的外观和样式。
  3. 资源共享:资源字典允许在应用程序的不同部分共享资源。这意味着您可以在不同的页面、窗口或控件中引用和使用相同的资源,以实现一致性和统一性。
  4. 动态更新:资源字典中的资源可以动态更新。当修改资源字典中的资源时,引用了该资源的控件会自动更新其外观和行为,而无需手动修改每个控件。
  5. 可扩展性:资源字典可以很容易地进行扩展和定制。可以在已有的资源字典基础上添加新的资源,或者创建自己的自定义资源字典,并将其与应用程序中的其他资源字典进行组合和使用。

查找资源

在WPF中,可以使用以下几种方法通过后台代码查找资源:

  1. 使用FindResource方法:这是一种常用的方法,通过调用控件或应用程序的FindResource方法来查找资源。该方法会在当前元素及其父级元素的资源字典中进行查找,并返回找到的资源对象。例如:

    var resource = this.FindResource("ResourceKey");
  2. 使用TryFindResource方法:与FindResource方法类似,但是TryFindResource方法不会抛出异常,而是返回一个布尔值表示是否找到了资源。这样可以更容易地处理资源查找失败的情况。例如:

    bool found = this.TryFindResource("ResourceKey", out var resource);
  3. 使用Resources属性:每个FrameworkElement都有一个Resources属性,该属性是一个ResourceDictionary对象,它包含了该元素的资源字典。可以通过访问该属性来查找资源。例如:

    var resource = this.Resources["ResourceKey"];
  4. 使用Application.Current.Resources:可以通过访问Application.Current.Resources属性来查找应用程序级别的资源。这个属性返回一个ResourceDictionary对象,其中包含了整个应用程序的资源。例如:

    var resource = Application.Current.Resources["ResourceKey"];

以上就是本文的全部内容了,主要介绍了WPF中的两大类资源:应用资源和XAML 资源以及在使用资源时通过静态资源引用和使用动态资源引用的区别,需要根据具体场景调整。

本文是学习WPF所作笔记,内容难免由纰漏,欢迎留言讨论!

WPF 入门笔记 - 04 - 数据绑定 - 补充内容:资源基础的更多相关文章

  1. WPF 入门笔记之控件内容控件

    一.控件类 在WPF中和用户交互的元素,或者说.能够接受焦点,并且接收键盘鼠标输入的元素所有的控件都继承于Control类. 1. 常用属性: 1.1 Foreground:前景画刷/前景色(文本颜色 ...

  2. WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush)

    原文:WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 前面我们提到了LinearGradientBrush可以用来画渐变填充图,那么我们同时也可以使用ImageBr ...

  3. WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush)

    原文:WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush) 前面我们介绍到,Path对象表示一个用直线或者曲线连接的图形,我们可以使用Path.Data ...

  4. WPF 入门笔记之事件

    一.事件路由 1. 直接路由事件 起源于一个元素,并且不能传递给其他元素 MouserEnter 和MouserLeave 就是直接事件路由 2. 冒泡路由事件 在包含层次中向上传递,首先由引发的元素 ...

  5. WPF 入门笔记之布局

    一.布局原则: 1. 不应显示的设定元素的尺寸,反而元素可以改变它的尺寸,并适应它们的内容 2. 不应使用平布的坐标,指定元素的位置. 3. 布局容器和它的子元素是共享可以使用的空间 4. 可以嵌套的 ...

  6. WPF 入门笔记之基础

    一.创建WPF程序 1. App.xaml 相当于窗体的配置文件 2. xmlns:xml名称空间的缩写 xmlns="http://schemas.microsoft.com/winfx/ ...

  7. 【python3两小时根本不够】入门笔记04:线程+Lock安全同步

    有了简单爬虫,但是效率实在是太慢,于是决定启用线程进行爬取数据 但是对于临界资源的定义不好把握,思路如下: 1.定义队列(Queue的数据结构,List也可,安全性待考究) demo:https:// ...

  8. matlab入门笔记(六):编程基础之M文件

    摘自<matlab从入门到精通>胡晓东 在Matlab中,用户可以在命令行中直接输入命令,从而以一种交互式的方式来编写程序.这种方式适用于命令行比较简单,输入比较方便,同时处理的问题较少的 ...

  9. Redis:学习笔记-04

    Redis:学习笔记-04 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 10. Redis主从复制 1 ...

  10. WPF入门:数据绑定

    上一篇我们将XAML大概做了个了解 ,这篇将继续学习WPF数据绑定的相关内容 数据源与控件的Binding Binding作为数据传送UI的通道,通过INotityPropertyChanged接口的 ...

随机推荐

  1. R语言文本数据挖掘(四)

    文本分词,就是对文本进行合理的分割,从而可以比较快捷地获取关键信息.例如,电商平台要想了解更多消费者的心声,就需要对消费者的文本评论数据进行内在信息的数据挖掘分析,而文本分词是文本挖掘的重要步骤.R语 ...

  2. 京东获得店铺的所有商品API接口(item_search_shop-获得店铺的所有商品)

    京东获得店铺的所有商品API接口(item_search_shop-获得店铺的所有商品)接口展示说明及教程: 公共参数 名称 类型 必须 描述key String 是 调用key(必须以GET方式拼接 ...

  3. 华为 A800-9000 服务器 离线安装MindX DL

    MindX DL(昇腾深度学习组件)是支持 Atlas 800 训练服务器.Atlas 800 推理服务器的深度学习组件参考设计,提供昇腾 AI 处理器资源管理和监控.昇腾 AI 处理器优化调度.分布 ...

  4. [Java]排序算法>交换排序>【冒泡排序】(O(N*N)/稳定/N较小/有序/顺序+链式)

    1 冒泡排序 1.1 算法思想 交换排序的基本思想:两两比较待排序记录的关键字,一旦发现2个记录不满足次序要求时,则:进行交换,直到整个序列全部满足要求为止. 1.2 算法特征 属于[交换排序] 冒泡 ...

  5. mapper接口中常见的增删改查

    前言 相信大家在使用mybatis写mapper接口的时候,最常用且简单的方法就是增删改查了.我也是刚开始做项目,在本篇文章中,我将根据自己在vhr微人力项目中的mapper接口方法为实例,记录一下接 ...

  6. redhat6安装10g rac过程中的报错

    问题描述:redhat 6 来安装oracle10.2.0.1的集群,坑太多了,不建议这样安装,即使安装成功,在升级过程中也会有各种报错.redhat5安装还比较顺利,6就一路坑 1.缺少依赖 lib ...

  7. boot-admin整合Liquibase实现数据库版本管理

    Liquibase 和 Flyway 是两款成熟的.优秀的.开源/商业版的数据库版本管理工具,鉴于 Flyway 的社区版本对 Oracle 数据库支持存在限制,所以 boot-admin 选择整合 ...

  8. 使用 Sa-Token 完成踢人下线功能

    一.需求 在企业级项目中,踢人下线是一个很常见的需求,如果要设计比较完善的话,至少需要以下功能点: 可以根据用户 userId 踢出指定会话,对方再次访问系统会被提示:您已被踢下线,请重新登录. 可以 ...

  9. 2023-01-09:以下go语言代码输出什么?A:+Inf; B:zero; C:something else; D:doesn‘t compile。 package main import (

    2023-01-09:以下go语言代码输出什么?A:+Inf: B:zero: C:something else: D:doesn't compile. package main import ( & ...

  10. 2022-02-11:单词缩写。 给定一个由n个不重复非空字符串组成的数组,你需要按照以下规则为每个单词生成最小的缩写。 初始缩写由起始字母+省略字母的数量+结尾字母组成。 若存在冲突,亦即多于一个单

    2022-02-11:单词缩写. 给定一个由n个不重复非空字符串组成的数组,你需要按照以下规则为每个单词生成最小的缩写. 初始缩写由起始字母+省略字母的数量+结尾字母组成. 若存在冲突,亦即多于一个单 ...