麓野 发表于 2023-11-7 19:17:05

[WPF]浅析资源引用(pack URI)

WPF中我们引用资源时常常提到一个概念:pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI,这是WPF标识和引用资源最常见的方式,但不是唯一的方式。本文将介绍WPF中引用资源的几种方式,并回顾一下pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI标识引用在不同位置的资源文件的写法。
WPF中引用资源的几种方式

WPF中使用URI标识和加载位于各种位置的文件,包括当前程序集资源文件、其他程序集资源文件、本地磁盘文件、网络共享文件、web站点文件。
程序集资源文件

程序集资源文件是最常见的一种情况。这里程序集资源指的是资源文件属性的生成操作(Build<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Action)为Resource的文件,而非嵌入的资源(Emmbedded<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Resource)。程序集中的资源文件通常使用相对URI来引用,例如:
<ImageBrush<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> x:Key="imgbrush"<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> ImageSource="images/111.jpg"/><ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> //本地程序集中资源引用的写法
<ImageBrush<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> x:Key="imgbrush"<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> ImageSource="/ResourceDll;component/images/111.jpg"/><ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> //引用的程序集中资源引用的写法也可以使用绝对Pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI语法,例如
<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> x:Key="imgbrush"<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> ImageSource="images/111.jpg"/><ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> //本地程序集中资源引用的写法
<ImageBrush<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> x:Key="imgbrush"<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> ImageSource="/ResourceDll;component/images/111.jpg"/><ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> //引用的程序集中资源引用的写法本地磁盘文件

直接引用本地磁盘文件的方式不常见。这种方式引用本地文件会占用文件,本地文件无法修改或者删除,因此不推荐此方式。这里只是举例讲解。
<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 网络共享文件

网络共享文件和本地磁盘文件类似,会占用文件。可以使用UNC或者URI的方式引用。
<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> UNC方式引用<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> <ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI方式引用web站点文件

少数场景下会在WPF中使用web站点资源,比如用户头像。web站点资源主要以http/https协议的url加载,url作为URI的子集,因此可以直接引用。实际开发中不建议直接引用url,因为请求网络资源需要时间,这可能导致UI短暂卡顿。建议开启线程把网络资源读到内存中使用。
上述示例中都是在XAML中声明式的语法引用资源,本质还是使用Uri类,因此在后台代码中使用Uri类就行。
//<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 绝对URI<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> (默认)Uri<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> absoluteUri<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> =<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> new<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Uri("pack://application:,,,/images/111.jpg",<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> UriKind.Absolute);//<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 相对URIUri<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> relativeUri<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> =<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> new<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Uri("images/111.jpg",<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> UriKind.Relative);Pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI方案

pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI的语法看起来很奇怪,它是来自开放式打包约定<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> (OPC)规范中XPS(XML<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Paper<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Specification)标准,有使用openxml解析Word/PPT文件经验的朋友可能熟悉这个规范。OPC<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 规范利用RFC<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 2396(统一资源标识符<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> (URI):一般语法)的扩展性来定义pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI方案。
URI所指定的方案(schemes)由其前缀定义;http、ftp、telnet和file<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 是比较常见的协议方案(schemes)。pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI使用“pack”作为它的方案(schemes),并且包含两个组件:授权和路径。<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI的格式为:pack://authority/path。authority指定包含部件的包的类型,而path<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 指定部件在包内的位置。前边示例代码中application:,,,就是授权(authority),/images/111.jpg或者/ResourceDll;component/images/111.jpg就是路径(path)。这里也可以理解为嵌套在方案(schemes)为pack://的uri中的uri。由于是嵌套在内部的uri,授权(authority)原本应是application:///中的斜杠转义为逗号。路径中必须对保留字符(如“%”和“?”)进行转义。详细信息可参阅开放式打包约定<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> (OPC)规范
标准的URI协议方案有30种左右,由隶属于国际互联网资源管理的非营利社团<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> ICANN(Internet<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Corporation<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> for<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Assigned<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Names<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> and<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Numbers,互联网名称与数字地址分配机构)的<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> IANA(Internet<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Assigned<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Numbers<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Authority,互联网号码分配局)管理颁布。详细协议方案参见:http://www.iana.org/assignments/uri-schemes
在WPF中,用程序(包)可以包含一个或多个文件(部件),包括:

[*]当前程序集内的资源文件
[*]引用的程序集内的资源文件
[*]内容文件
[*]源站点文件
为了访问这些类型的文件,WPF<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 支持两种授权:application:///和siteoforigin:///。<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> application:///<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 授权标识在编译时已知的应用程序数据文件,包括资源文件和内容文件。<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> siteoforigin:///<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 授权标识源站点文件。<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 下图显示了每种授权的范围。

pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI语法示例

前边提到pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI由授权和路径组成,当前程序集、引用的程序集内的资源文件,以及内容文件的授权都是application:///,源站点文件的授权是siteoforigin:///(用于XAML浏览器应用程序)。
当前程序集资源文件

当前程序集资源文件的路径是资源文件相对程序集项目文件夹根目录的路径。需要注意的是这里所说的相对于程序集项目文件夹根目录表达的是从哪里开始作为根目录进行寻址,当使用pack://这样绝对URI表示时,路径应该用根目录符号/开始。下图中111.jpg位于项目的根目录,它的pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI就是:
pack://application:,,,/111.jpgBlindsShader.ps位于子目录中,它的pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI就是:
pack://application:,,,/Shader/ShaderSource/BlindsShader.ps
引用程序集资源文件

当需要引用另一个程序集中的资源文件时,路径需要指明程序集的名称。路径需符合以下的格式:
pack://application:,,,AssemblyShortName{;Version}{;PublicKey};component/ResourceName

[*]AssemblyShortName是引用的程序集的短名称,是必选项
[*]Version是引用的程序集的版本。此部分在加载两个或多个具有相同短名称的引用程序集时使用,是可选项。
[*]PublicKey是引用的程序集的签名公钥。此部分在加载两个或多个具有相同短名称的引用程序集时使用,是可选项。
[*]component指定所引用的程序集是从本地程序集引用的,此处是固定写法
[*]ResourceName是资源文件的名称,包括其相对于所引用程序集的项目文件夹根目录的路径。
内容文件

前边提到的资源文件都是生成操作(Build<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Action)为Resource的文件,是会编译到程序集中。内容文件是生成操作(Build<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> Action)为内容(Content)的文件,并不会编译到程序集中,通常是将文件属性中复制到输出目录(CopyToOutputDirectory)选为始终复制(Always)或者如果较新则复制(PreserveNewest),将文件保存到程序运行目录中。内容文件主要可以解决以下问题:

[*]改变资源文件时,需要重新编译应用程序;
[*]资源文件比较大,导致编译的程序集也比较大;
[*]WPF声音文类不支持程序集资源,无法从资源流中析取音频文件并播放。
内容文件本质上也是本地磁盘文件,但生成项目时,会将<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> AssemblyAssociatedContentFileAttribute<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 属性编译到每个内容文件的程序集的元数据内,AssemblyAssociatedContentFileAttribute<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 的值表示内容文件相对于其在项目中的位置的路径[^2],可以采用pack<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> URI的方式加载。内容文件的路径是其相对于应用程序的主可执行程序集的文件系统位置的路径。其格式如下:
pack://application:,,,/ContentFile.wav源站点文件

源站点文件主要针对XAML浏览器应用程序(XBAP)设计,编译XAML浏览器应用程序(XBAP)将资源文件分离出程序集,减少文件大小,在需要请求下周源站点文件时,才下载它们到客户端计算机[^2]。现在基本不适用该技术,本文不再详细介绍,感兴趣可以查看文末参考资料。
参考

[^1]<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/app-development/pack-uris-in-wpf?view=netframeworkdesktop-4.8
[^2]<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/app-development/wpf-application-resource-content-and-data-files?view=netframeworkdesktop-4.8

来源:https://www.cnblogs.com/czwy/archive/2023/11/07/17815776.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】<ImageBrush x:Key="imgbrush" ImageSource="d:\\tmp\\新建文件夹\\123.jpg"/> 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: [WPF]浅析资源引用(pack URI)