WPF之资源
WPF不但支持程序级的传统资源,同时还推出了独具特色的对象级资源,每个界面元素都可以携带自己的资源并可被自己的子级元素共享。
WPF对象资源的定义和查找
每个WPF界面元素都有一个名为Resource的属性,其类型为ResourceDictionary(继承至FrameworkElement类)。
ResourceDictionary能够以键值对的形式存储资源,当要使用到某个资源的时候,使用键值对的形式获取资源对象。
在保存资源时,ResourceDictionary视资源对象为Object类型,使用资源时先要对资源对象进行类型转换,XAML编译器能够根据Attribute自动识别资源类型(类型不对就会抛出异常),在C#中需要手动对资源对象进行类型转换。
ResourceDictionary可以存储任意类型的对象,在XAML代码中向Resource添加资源时需要把正确的命名空间引入到XAML代码中,如下所示:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="100" Width="300">
<Window.Resources>
<ResourceDictionary>
<sys:String x:Key="str">沉舟侧畔千帆过,病树前头万木春。</sys:String>
<sys:Double x:Key="db">3.1415926</sys:Double>
</ResourceDictionary>
</Window.Resources>
<StackPanel>
<TextBlock Text="{ StaticResource ResourceKey=str}"/>
<!--<TextBlock Text="{StaticResource ResourceKey=db}"/> 类型错误-->
</StackPanel>
</Window>
将System命名空间引入XAML代码中并映射为sys名称空间,然后在Windows.Resource里面添加了两个资源条目,一个是string类型,一个是double类型。
用两个textBlock来消费这两个资源(被注释掉的代码因为数据类型不匹配而抛出异常),程序运行效果如下图:

在XAML代码里面可以对集合类容及标签扩展进行简写,上面代码的常见书写格式如下:
<TextBlock Text="{ StaticResource str}"/>
在查找资源时,先查找控件自己的Resource属性,如果没有这个资源程序会沿着逻辑树向上一级进行查找,如果连最顶端容器都没有这个资源,程序就会查找Application.Resource(也就是程序的顶级资源)。如果还没有找到,那么就只能抛出异常了。
在C#代码里面使用XAML代码里面定义的资源,格式如下:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string text = (string)this.FindResource("str");
textBox.Text = text;
}
明确知道资源放在那个资源字典里,可以这样检索资源:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string text = (string)this.Resources["str"];
textBox.Text = text;
}
WPF的资源可以做到像CSS或者JS一样放在独立的文件夹里,使用时成套引用、重用时便于分发,只要把包含资源定义的文件路径赋值给ResourceDictionary的Source属性即可:
<Window.Resources>
<ResourceDictionary Source="ShinyRed.xaml"/>
</Window.Resources>
动态、静态使用资源
当资源被存储进资源词典之后,可以使用两种方式来使用这些资源-----静态方式和动态方式。
对于资源的使用,Static指的是程序的非执行状态而Dynamic指的是程序的运行状态。
静态资源使用StaticResource指的是程序载入内存时对资源的一次性使用(之后不在访问),动态资源(DynamicResource)使用指的是在程序运行过程中仍然会去访问资源。
在Windows资源字典里放置了两个TextBlock类型资源,并分别以StaticResource和DynamicResource方式使用之:
<Window.Resources>
<ResourceDictionary>
<TextBlock x:Key="res1" Text="海上生明月"/>
<TextBlock x:Key="res2" Text="海上生明月"/>
</ResourceDictionary>
</Window.Resources>
<StackPanel>
<Button Margin="5,5,5,0" Content="{StaticResource res1}" />
<Button Margin="5,5,5,0" Content="{DynamicResource res2}"/>
<Button Margin="5,5,5,0" Content="Update" Click="Button_Click"/>
</StackPanel>
界面上的第三个按钮负责在程序运行过程中对资源词典里面的两个资源进行改变:
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Resources["res1"] = new TextBlock() { Text = "天涯共此时" };
this.Resources["res2"] = new TextBlock() { Text = "天涯共此时" };
}
第一个按钮是以静态方式使用资源,尽管资源已经更新它也不知道。
运行程序,单击第三个按钮,效果如下图:

向程序添加二进制资源
常见的应用程序资源有图标、图片、文本、音频、视频等,各种编程语言的编译器或者资源编译器都有能力把这些文件编译进目标文件(最终的.exe文件或者.dll文件)。
资源文件在目标文件里以二进制数据形式存在、形成目标文件的资源段(Resource Section),使用时数据会被提取出来。
为了区分,称呼资源词典里面的资源为“WPF资源”或“对象资源”,称呼应用程序内嵌资源为“程序集资源”或者“二进制资源”。WPF中写在<Application.Resource>...</Application.Resource>标签内的资源仍然是WPF资源而非二进制资源。
字符串资源
如果要添加的资源是字符串而非文件,可以使用应用程序名称空间下的Resources.resx资源文件。打开资源文件的方法是项目管理器中展开Properties文件夹,并双击下面的Resources.resx资源文件。
Resources.resx文件内容的组织形式是“键-值”对,编译后Resources.resx会形成Properties名称空间中的Resource类,使用这个类的方法或属性就能获取资源。
在资源文件的字符串组里添加两个条目,然后分别在XAML代码和C#代码中访问它们。一定要在资源文件编辑器里把Resources.resx的访问级别由Internal改为public,否则运行会报错。
在XAML代码中使用Resources.resx中的资源,需要把程序的Properties名称映射为XAML名称空间,然后使用x:Static标签扩展来访问资源:
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prop="clr-namespace:WpfApp.Properties"
Title="MainWindow" Height="130" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="4" />
<RowDefinition Height="23" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="4" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Static prop:Resources.UserName}"/>
<TextBlock x:Name="textBlockPassword" Grid.Row="2"/>
<TextBox BorderBrush="Black" Grid.Column="2"/>
<TextBox BorderBrush="Black" Grid.Row="2" Grid.Column="2"/>
</Grid>
</Window>
C#中访问Resources.resx的资源如下:
this.textBlockPassword.Text = Properties.Resources.Password;
效果如下:

使用Resources.resx最大的好处就是便于程序国际化,本地化。
非字符串资源
如果要添加的资源不是字符串,而是图标、图片、音频或者视屏,就不能使用Resources.resx了,WPF不支持这么做。在WPF使用外部文件作为资源,仅需要将其简单的放入项目即可。
方法是在项目管理器上右击项目名称,在弹出的菜单里选择“添加”-->“新建文件夹”,按需要新建几层文件夹来存放资源,然后在恰当的文件夹上右击,在弹出的菜单里选择“添加”--->“现有项”,在文件对话框里选择文件后单击“添加”按钮,文件就以资源的形式加入项目中了。
如果想让外部文件编译进二进制资源,必须在属性窗口把文件的“生成操作”属性值设为“Resource”。并不是每种文件都会自动设置为“Resource”,比如图片文件会,MP3文件就不会,一般情况下,如果“生成操作”的值设为“Resource”,则“复制到输出目录”属性设置为“不复制”;如果不希望以资源的形式使用外部文件,可以把“生成操作”属性设置为“无”,而把“复制到输出目录”设置为“始终复制”。另外,“生成操作”属性的下拉列表里面有一个颇具迷惑性的值“嵌入的资源”,不要选择这个值。
使用Pack URI路径访问二进制资源
WPF对二进制资源的访问有自己的一套方法,称为Pack URI路径。WPF的Pack URI路径只需要记住以下格式:
pack://application,,,[/程序集名称;][可选版本号;][文件夹名称/][文件名称]
实际上pack://applicationi,,,可以省略、程序集名称和版本号常使用省略值,剩下的就只有以下内容:
[文件夹名称/][文件名称]
访问Resource/Images/Rafale.gif,用这个图片填充一个<Image/>元素并把<image/>元素作为窗体的背景。
XAML代码如下:
<Image Source="Resource/Images/Rafale.gif" x:Name="ImageBg" Stretch="Fill"/>
<!--或-->
<Image Source="pack://application:,,,/Resource/Images/Rafale.gif" x:Name="ImageBg" Stretch="Fill"/>
等价的C#代码如下:
Uri imgUri = new Uri(@"Resource/Images/Rafale.gif",UriKind.Relative);
//或
//Uri imgUri = new Uri(@"pack://application:,,,/Resource/Images/Rafale.gif", UriKind.Absolute);
this.ImageBg.Source = new BitmapImage(imgUri);
在使用Pack URI路径时有以下几点需要注意:
- Pack URI使用的是从右向左的正斜线(/)表示路径。
- 使用所略写意味着相对路径,C#代码中的UriKind必须为Relative而且代表根目录的/可以省略。
- 使用完整写法时是绝对路径,C#代码中的UriKind必须为Absolute并且代表根目录的/不能省略。
- 使用相对路径可以借助类似DOS的语法进行导航,比如./代表同级目录,../代表父级目录。
WPF之资源的更多相关文章
- WPF之资源字典zz
最近在看wpf相关东西,虽然有过两年的wpf方面的开发经验,但是当时开发的时候,许多东西一知半解,至今都是模模糊糊,框架基本是别人搭建,自己也就照着模板写写,现在许多东西慢慢的理解了,回顾以前的若干记 ...
- WPF 之 资源(Resource)
1.什么叫WPF的资源(Resource)? 资源是保存在可执行文件中的一种不可执行数据.在WPF的资源中,几乎可以包含图像.字符串等所有的任意CLR对象,只要对象有一个默认的构造函数和独立的属性. ...
- WPF 中资源路径的问题
WPF 中资源路径的问题 1. 引用当前工程的资源(注意xxxx.png的build action 应设置为Resource 或Embedded Resource) <ImageBrush Im ...
- WPF样式资源文件简单运用
WPF通过资源来保存一些可以被重复利用的样式,下面的示例展示了简单的资源样式文件的使用: 一.xaml中定义资源及简单的引用 <Window.Resources > <!--wpf窗 ...
- WPF 访问资源中的Storyboard
原文:WPF 访问资源中的Storyboard <UserControl.Resources> <Storyboard x:Key="testStoryboard" ...
- WPF学习资源整理
WPF(WindowsPresentation Foundation)是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分.它提供了统一的编程模型 ...
- WPF 调用资源图片
原文:WPF 调用资源图片 最近做的wpf项目中,在开发的时候,把图片放到了bin下面,采用了imagePath =System.IO.Directory.GetCurrentDirectory()+ ...
- WPF - 资源收集
原文:WPF - 资源收集 OpenExpressApp的UI现在是使用WPF,所以熟悉WPF是必须的,以下我将可能用到的一些相关内容随时记录下来,以备查阅.此篇文章将不断更新,感兴趣的可以看看,也欢 ...
- WPF 为资源字典 添加事件响应的后台类
原文:WPF 为资源字典 添加事件响应的后台类 前言,有许多同学在写WPF程序时在资源字典里加入了其它控件,但又想写事件来控制这个控件,但是资源字典没有CS文件,不像窗体XAML还有一个后台的CS文件 ...
- WPF之资源专题
1.一般程序的资源可以分为四个等级: 数据库中的数据相当于放在仓库里 资源文件里的数据相当于放在旅行箱里 WPF对象资源里的数据相当于携带在背包里 变量中的数据相当于拿在手里 2.资源的查找顺序是沿着 ...
随机推荐
- 在Golang中实现多态
目录 1.说明 2.多态 3.代码示例 4.总结 1.说明 和流行的面向对象语言不同,go 中没有面向对象的说法,也没有对应的封装.继承和多态,也许 go 的设计就不是和OOP对齐,想使用OOP,那就 ...
- git~issue在github/gitlab中的使用
本文档适用于github和gitlab issue介绍 GitHub 中的 issue 功能是一种用于跟踪项目中任务.缺陷.功能请求和讨论的工具.通过 issue,项目成员可以提出问题.报告 bug. ...
- SpringBoot 多模块开发 笔记(一)
多模块开发 简易版 dao 层 也可以说是 Mapper 层 web 层 将 controller 放在这一层 还有 统一返回类型 和 自定义异常 也在放在这里 启动类也放在这里 model 层 也就 ...
- 新零售SaaS架构:促销系统架构设计
促销业务概述 什么是促销? 促销是商家用来吸引消费者购物的一种手段,目的是让更多的人知道并购买他们的产品,这样就能卖得更多.促销的方法有很多种,比如,价格优惠.赠品.优惠券.折扣.买一赠一等形式. 特 ...
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第7章)-- 读书笔记(下)
第 7 章 高级主题 7.4 HATEOAS 全称 Hypermedia AS The Engine Of Application State,即超媒体作为应用程序状态引擎.它作为 REST 统一界面 ...
- DRF解决跨域问题
Django Rest Framework提供了corsheaders模块解决跨域问题 安装模块 pip3.9 install django-cors-headers 注册应用 # 注册 corshe ...
- Slot 的含义
Slot 解释 1)slot就是槽的意思,是一个资源单位,只有给task分配了一个slot之后,这个task才可以运行.slot分两种,map slot沪蓉reduce slot.另外,slot是一个 ...
- win10安装和配置weblogic12c
下载和安装 http://www.oracle.com/technetwork/middleware/ias/downloads/wls-main-097127.html ● 将jar放到jdk的bi ...
- Vue+SpringBoot+ElementUI实战学生管理系统-7.专业管理模块
1.章节介绍 前一篇介绍了院系管理模块,这一篇编写专业管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 专业列表 修改专业 4.模块 ...
- Java中交换2个变量的三种方式
这一题是我之前找Java工作时的笔试题,比较有代表性,拿出来和大家分享. package com.dylan.practice.interview; /** * 交换2个整形变量的几种方式 * * @ ...