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.资源的查找顺序是沿着 ...
随机推荐
- Win32汇编:汇编版PE结构解析器
PE格式是Windows系统下最常用的可执行文件格式,有些应用必须建立在了解PE文件格式的基础之上,如可执行文件的加密与解密,文件型病毒的查杀等,熟练掌握PE文件结构,有助于软件的分析. 在PE文件中 ...
- C/C++可变参数模版和函数指针的结合
目录 1.说明 2.模板类传入固定参数的C函数指针 3.模板类传入固定参数的C++函数指针 3.1.用函数对象替代函数指针存储 4.模板类传入不定参数的C函数指针 5.模板类传入不定参数的C++成员函 ...
- 创建framework静态库和.a静态库
在APP项目中使用的静态库有两种,一是.a静态库,另一种是framework静态库.下面分布介绍这2中静态库的创建过程,以及通过脚本工具做自动化打包的2种方式. Framework静态库生成 如果 ...
- Oracle 数据库锁表问题及相关解决方法
Oracle 数据库锁表问题及相关解决方法 问题描述: 今天在公司运行服务的时候,需要查询300多万的数据,再进行排序之后放到kafka的消息队列中,供flink进行消费.在服务器上直接运行后,服务报 ...
- 洛谷P1249最大乘积,数论找规律
这道题是数论加高精度,高精度倒好说,就是高精度乘法实现,模拟列竖式乘法,但是找出要乘的这几个数实属不容易,没学过数论,只能从题解中学怎么找规律这里引用一下洛谷题解区赞数最高的题解 不知道大家看其他的题 ...
- 下载安装JDK 和 IntelliJ IDEA 和 ActiveMq
wget http://yun.diandaxia.com/other/jdk-8u92-linux-x64.rpm rpm -ivh jdk-8u92-linux-x64.rpm wget http ...
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第7章)-- 读书笔记(中)
第 7 章 高级主题 7.2 并发 当两个用户获取同一个资源后,再同时修改该资源,就会导致并发问题 常见实现并发的方法有以下两种: 保守式并发控制,每次修改资源,都锁定资源 开放式并发控制,每次修改资 ...
- .NET Core开发实战(第1课:课程介绍)--学习笔记
01 | 课程介绍 讲师介绍 肖伟宇,校宝在线架构师.SkyWalking .NET探针贡献者.NetCorePal组件库创建者 为什么要学习 .NET Core 微软大力支持推动 .Net 技术生态 ...
- C# 二十年语法变迁之 C# 2,C# 3 ,C# 4参考
C# 二十年语法变迁之 C# 2,C# 3 ,C# 4参考 https://benbowen.blog/post/two_decades_of_csharp_i/ 自从 C# 于 2000 年推出以来 ...
- mysql 外键索引入门介绍,为什么工作中很少有人使用?
背景 以前工作学习中,一直被告诫不要使用外键,所以也没有仔细整理过. 这里记录一下笔记. 外键 是什么? MySQL 的外键(Foreign Key)是一种关系型数据库中用于建立表与表之间关联关系的重 ...