参考资源网http://msdn.microsoft.com/zh-cn/library/aa970069.aspx#Absolute_vs_Relative_Pack_URIs

在 Windows Presentation Foundation (WPF) 中,使用统一资源标识符 (URI) 标识和加载文件的方式有很多,包括:

  • 指定当应用程序第一次启动时显示的用户界面 (UI)。

  • 加载图像。

  • 导航到页

  • 加载不可执行的数据文件。

此外,可以使用 URI 标识和加载位于各种位置的文件,这些位置包括:

  • 当前程序集。

  • 所引用的程序集。

  • 相对于程序集的某个位置。

  • 应用程序的源站点。

为了提供从这些位置标识和加载上述类型的文件的一致机制,WPF 利用了 pack URI 方案的扩展性。 本主题将概述这一方案,介绍如何为各种方案构造 pack URI,讨论绝对和相对 URI 以及 URI 解析,然后说明如何在标记和代码中使用 pack URI。

本主题包括下列各节。

Pack URI 方案由 Open Packaging Conventions(开放式打包约定,OPC)规范使用,该规范描述用于组织和标识内容的模型。 此模型的关键元素是程序包和部件,其中,“程序包”是一个或多个逻辑“部件”的逻辑容器。 下图阐释了此概念。

为了标识部件,OPC 规范利用 RFC 2396(统一资源标识符 (URI):一般语法)的扩展性来定义 pack URI 方案。

URI 所指定的方案由其前缀定义;http、ftp 和 file 是众所周知的示例。 Pack URI 方案使用“pack”作为它的方案,并且包含两个组件:授权和路径。 以下是 pack URI 的格式。

pack://授权/路径

授权 指定包含部件的程序包的类型,而路径 则指定部件在程序包中的位置。

下图阐释了此概念:

程序包和部件之间的关系类似于应用程序和文件之间的关系,其中,应用程序(程序包)可以包含一个或多个文件(部件),包括:

  • 编译到本地程序集中的资源文件。

  • 编译到所引用的程序集中的资源文件。

  • 编译到进行引用的程序集中的资源文件。

  • 内容文件。

  • 源站点文件。

为了访问这些类型的文件,WPF 支持两种授权:application:/// 和 siteoforigin:///。 Application:/// 授权标识在编译时已知的应用程序数据文件,包括资源文件和内容文件。 Siteoforigin:/// 授权标识源站点文件。下图显示了每种授权的范围。

 说明

Pack URI 的授权组件是一个嵌入式 URI,它指向程序包并且必须符合 RFC 2396。 另外,必须用字符“,”替换字符“/”,并且必须对保留字符(如“%”和“?”)进行转义。 有关详细信息,请参见 OPC。

以下各节解释如何将这两种授权与用于标识资源、内容和源站点文件的相应路径结合起来,以便构造 pack URI。

将资源文件配置为 MSBuild Resource 项并将其编译到程序集中。 WPF 支持构造可用于标识资源文件的 Pack URI,这些资源文件要么编译到本地程序集中,要么编译到从本地程序集引用的程序集中。

本地程序集资源文件

编译到本地程序集中的资源文件的 pack URI 使用以下授权和路径:

  • 授权:application:///。

  • 路径:资源文件的名称,包括它的相对于本地程序集项目文件夹根目录的路径。

下面的示例演示一个 XAML 资源文件的 pack URI,该资源文件位于本地程序集的项目文件夹的根目录中。

pack://application:,,,/ResourceFile.xaml

下面的示例演示一个 XAML 资源文件的 pack URI,该资源文件位于本地程序集的项目文件夹的子文件夹中。

pack://application:,,,/Subfolder/ResourceFile.xaml

所引用的程序集资源文件

编译到所引用的程序集中的资源文件的 pack URI 使用以下授权和路径:

  • 授权:application:///。

  • 路径:编译到所引用的程序集中的资源文件的名称。 路径必须符合以下格式:

    程序集短名称[;版本][;公钥];组件/路径

    • 程序集短名称:所引用的程序集的短名称。

    • ;版本 [可选]:所引用的包含资源文件的程序集的版本。 此部分在加载两个或多个具有相同短名称的所引用的程序集时使用。

    • ;公钥 [可选]:用于对所引用的程序集进行签名的公钥。 此部分在加载两个或多个具有相同短名称的所引用的程序集时使用。

    • ;组件:指定所引用的程序集是从本地程序集引用的。

    • /路径:资源文件的名称,包括它的相对于所引用程序集的项目文件夹根目录的路径。

下面的示例演示一个 XAML 资源文件的 pack URI,该资源文件位于所引用程序集的项目文件夹的根目录中。

pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml

下面的示例演示一个 XAML 资源文件的 pack URI,该资源文件位于所引用程序集的项目文件夹的子文件夹中。

pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

下面的示例演示一个 XAML 资源文件的 pack URI,该资源文件位于所引用的、特定于版本的程序集的项目文件夹的根文件夹中。

pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml

请注意,所引用的程序集资源文件的 pack URI 语法只能与 application:/// 授权一起使用。 例如,WPF 中不支持下面的格式。

pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml

内容文件的 pack URI 使用以下授权和路径:

  • 授权:application:///。

  • 路径:内容文件的名称,包括其相对于应用程序的主可执行程序集的文件系统位置的路径。

下面的示例演示一个 XAML 内容文件的 pack URI,该内容文件与可执行程序集位于同一个文件夹中。

pack://application:,,,/ContentFile.xaml

下面的示例演示一个 XAML 内容文件的 pack URI,该内容文件位于一个相对于应用程序的可执行程序集的子文件夹中。

pack://application:,,,/Subfolder/ContentFile.xaml

 说明

无法导航到 HTML 内容文件。 URI 方案仅支持导航到位于源站点的 HTML 文件。

源站点文件的 pack URI 使用以下授权和路径:

  • 授权:siteoforigin:///。

  • 路径:源站点文件的名称,包括其相对于启动可执行程序集的位置的路径。

下面的示例演示一个 XAML 源站点文件的 pack URI,该源站点文件存储在启动可执行程序集的位置。

pack://siteoforigin:,,,/SiteOfOriginFile.xaml

下面的示例演示一个 XAML 源站点文件的 pack URI,该源站点文件存储在相对于启动应用程序的可执行程序集的位置的子文件夹中。

pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml

被配置为 MSBuild Page 项的 XAML 文件按照与资源文件相同的方式编译到程序集中。 因此,可以使用资源文件的 pack URI 来标识 MSBuild Page 项。

通常被配置为 MSBuild Page 项的 XAML 文件类型将下列元素之一作为它们的根元素:

完全限定 pack URI 包括方案、授权和路径,它被视为绝对 pack URI。 作为一种针对开发人员的简化形式,XAML 元素通常允许您使用只包含路径的相对 pack URI 来设置相应的特性。

例如,假设本地程序集中的某个资源文件具有以下绝对 pack URI。

pack://application:,,,/ResourceFile.xaml

引用此资源文件的相对 pack URI 如下所示。

/ResourceFile.xaml

 说明

因为源站点文件不与程序集相关联,所以只能使用绝对 pack URI 引用源站点文件。

默认情况下,将相对 pack URI 视为相对于包含引用的标记或代码的位置。 但是,如果使用前导反斜杠,则将相对 pack URI 引用视为相对于应用程序的根目录。 例如,假设有以下项目结构。

App.xaml

Page2.xaml

\SubFolder

+ Page1.xaml

+ Page2.xaml

如果 Page1.xaml 包含引用“根目录\子文件夹\Page2.xaml”的 URI,则该引用可以使用下面的相对 pack URI。

Page2.xaml

如果 Page1.xaml 包含引用“根目录\Page2.xaml”的 URI,则该引用可以使用下面的相对 pack URI。

/Page2.xaml

Pack URI 的格式使得有可能让不同类型的文件的 pack URI 看起来相同。 例如,假设有以下绝对 pack URI。

pack://application:,,,/ResourceOrContentFile.xaml

此绝对 pack URI 可以引用本地程序集中的资源文件,也可以引用内容文件。 对于下面的相对 URI 来讲也是如此。

/ResourceOrContentFile.xaml

为了确定 pack URI 引用的文件的类型,WPF 使用下面的试探法来解析本地程序集中的资源文件以及内容文件的 URI:

  1. 探测与 pack URI 匹配的 AssemblyAssociatedContentFileAttribute 特性的程序集元数据。

  2. 如果找到 AssemblyAssociatedContentFileAttribute 特性,则 pack URI 的路径引用内容文件。

  3. 如果未找到 AssemblyAssociatedContentFileAttribute 特性,则探测编译到本地程序集中的资源文件集。

  4. 如果找到与 pack URI 的路径匹配的资源文件,则 pack URI 的路径引用资源文件。

  5. 如果未找到合适的资源,则内部创建的 Uri 无效。

URI 解析不适用于引用以下文件的 URI:

  • 所引用的程序集中的内容文件:WPF 不支持这些文件类型。

  • 所引用的程序集中的嵌入式文件:标识这些文件的 URI 是唯一的,因为它们既包含所引用的程序集的名称,又包含 ;component 后缀。

  • 源站点文件:标识这些文件的 URI 是唯一的,因为只有这些文件才能用包含 siteoforigin:/// 授权的 pack URI 进行标识。

Pack URI 解析所允许使用的一种简化形式是让代码在一定程度上独立于资源和内容文件的位置。 例如,如果本地程序集中有一个被重新配置为内容文件的资源文件,则该资源的 pack URI 会保留原样,而使用该 pack URI 的代码也是如此。

许多 WPF 类都实现了可以用 pack URI 设置的属性,包括:

可以从标记和代码中设置这些属性。 本节演示这两种设置方式的基本构造,然后演示通用方案示例。

在标记中使用 Pack URI

在标记中,使用 pack URI 设置某个特性的元素,从而指定 pack URI。 例如:

<element attribute="pack://application:,,,/File.xaml" />

表 1 阐释了可以在标记中指定的各种绝对 pack URI。

表 1:标记中的绝对 Pack URI

 

文件

绝对 pack URI

资源文件 — 本地程序集

"pack://application:,,,/ResourceFile.xaml"

子文件夹中的资源文件 — 本地程序集

"pack://application:,,,/Subfolder/ResourceFile.xaml"

资源文件 — 所引用的程序集

"pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml"

所引用的程序集的子文件夹中的资源文件

"pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"

所引用的版本化程序集中的资源文件

"pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml"

内容文件

"pack://application:,,,/ContentFile.xaml"

子文件夹中的内容文件

"pack://application:,,,/Subfolder/ContentFile.xaml"

源站点文件

"pack://siteoforigin:,,,/SOOFile.xaml"

子文件夹中的源站点文件

"pack://siteoforigin:,,,/Subfolder/SOOFile.xaml"

表 2 阐释了可以在标记中指定的各种相对 pack URI。

表 2:标记中的相对 Pack URI

 

文件

相对 pack URI

本地程序集中的资源文件

"/ResourceFile.xaml"

本地程序集的子文件夹中的资源文件

"/Subfolder/ResourceFile.xaml"

所引用的程序集中的资源文件

"/ReferencedAssembly;component/ResourceFile.xaml"

所引用的程序集的子文件夹中的资源文件

"/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"

内容文件

"/ContentFile.xaml"

子文件夹中的内容文件

"/Subfolder/ContentFile.xaml"

在代码中使用 Pack URI

在代码中,可以通过实例化 Uri 类并将 pack URI 作为参数传递给构造函数来指定 pack URI。 下面的示例说明了这一点。

 
Uri uri = new Uri("pack://application:,,,/File.xaml");

默认情况下,Uri 类将 pack URI 视为绝对 pack URI。 因此,在使用相对 pack URI 创建 Uri 类的实例时会引发异常。

 
Uri uri = new Uri("/File.xaml");

幸运的是,Uri 类构造函数的 Uri(String, UriKind) 重载可以接受一个类型为 UriKind 的参数,使您可以指定 pack URI 是绝对 URI 还是相对 URI。

 
// Absolute URI (default)
Uri absoluteUri = new Uri("pack://application:,,,/File.xaml", UriKind.Absolute);
// Relative URI
Uri relativeUri = new Uri("/File.xaml", UriKind.Relative);

当您能够确定所提供的 pack URI 是相对 pack URI 还是绝对 pack URI 的时候,应该只指定 Absolute 或 Relative。 如果您不了解所使用的 pack URI 的类型(例如,当用户在运行时输入 pack URI 时),请改用RelativeOrAbsolute

 
// Relative or Absolute URI provided by user via a text box
TextBox userProvidedUriTextBox = new TextBox();
Uri uri = new Uri(userProvidedUriTextBox.Text, UriKind.RelativeOrAbsolute);

表 3 阐释了可以在代码中使用 System.Uri 指定的各种绝对 pack URI。

表 3:代码中的绝对 Pack URI

 

文件

绝对 pack URI

资源文件 — 本地程序集

Uri uri = new Uri("pack://application:,,,/ResourceFile.xaml", UriKind.Absolute);

子文件夹中的资源文件 — 本地程序集

Uri uri = new Uri("pack://application:,,,/Subfolder/ResourceFile.xaml", UriKind.Absolute);

资源文件 — 所引用的程序集

Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Absolute);

所引用的程序集的子文件夹中的资源文件

Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Absolute);

所引用的版本化程序集中的资源文件

Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml", UriKind.Absolute);

内容文件

Uri uri = new Uri("pack://application:,,,/ContentFile.xaml", UriKind.Absolute);

子文件夹中的内容文件

Uri uri = new Uri("pack://application:,,,/Subfolder/ContentFile.xaml", UriKind.Absolute);

源站点文件

Uri uri = new Uri("pack://siteoforigin:,,,/SOOFile.xaml", UriKind.Absolute);

子文件夹中的源站点文件

Uri uri = new Uri("pack://siteoforigin:,,,/Subfolder/SOOFile.xaml", UriKind.Absolute);

表 4 阐释了可以在代码中使用 System.Uri 指定的各种相对 pack URI。

表 4:代码中的相对 Pack URI

 

文件

相对 pack URI

资源文件 — 本地程序集

Uri uri = new Uri("/ResourceFile.xaml", UriKind.Relative);

子文件夹中的资源文件 — 本地程序集

Uri uri = new Uri("/Subfolder/ResourceFile.xaml", UriKind.Relative);

资源文件 — 所引用的程序集

Uri uri = new Uri("/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Relative);

子文件夹中的资源文件 — 所引用的程序集

Uri uri = new Uri("/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Relative);

内容文件

Uri uri = new Uri("/ContentFile.xaml", UriKind.Relative);

子文件夹中的内容文件

Uri uri = new Uri("/Subfolder/ContentFile.xaml", UriKind.Relative);

常见 Pack URI 方案

前面几节讨论了如何构造 pack URI 以标识资源文件、内容文件和源站点文件。 在 WPF 中,可以通过各种方式使用这些构造,下面的几节将介绍几种常见用法。

指定当应用程序启动时显示的 UI

StartupUri 指定当 WPF 应用程序启动时显示的第一个 UI。 对于独立应用程序,UI 可以是一个窗口,如下面的示例所示。

 
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />

独立应用程序和 XAML 浏览器应用程序 (XBAP) 还可以将页面指定为初始 UI,如下面的示例所示。

 
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />

如果应用程序是独立应用程序,并且使用 StartupUri 指定了一个页面,则 WPF 会打开一个 NavigationWindow 以承载该页面。 对于 XBAP,该页面在宿主浏览器中显示。

导航到页面

下面的示例演示如何导航到页面。

 
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
WindowTitle="Page With Hyperlink"
WindowWidth="250"
WindowHeight="250"> ... <Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
Navigate to Another Page
</Hyperlink> ... </Page>

有关在 WPF 中导航的各种方式的更多信息,请参见导航概述

http://msdn.microsoft.com/zh-cn/library/aa970069.aspx#Absolute_vs_Relative_Pack_URIs

指定窗口图标

下面的示例演示如何使用 URI 指定窗口的图标。

 
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MainWindow"
Icon="WPFIcon1.ico">
</Window>

有关更多信息,请参见 Icon

加载图像、音频和视频文件

WPF 使应用程序可以使用各种媒体类型,所有这些媒体类型都可以用 pack URI 标识和加载,如下面的示例所示。

 
<MediaElement Stretch="Fill" LoadedBehavior="Play" Source="pack://siteoforigin:,,,/Media/bee.wmv" />
 
<MediaElement Stretch="Fill" LoadedBehavior="Play" Source="pack://siteoforigin:,,,/Media/ringin.wav" />
 
<Image Source="Images/Watermark.png" />

有关使用媒体内容的更多信息,请参见 图形和多媒体

从源站点加载资源字典

可以使用资源字典 (ResourceDictionary) 来支持应用程序主题。 创建和管理主题的一种方式是将多个主题创建为位于应用程序源站点的资源字典。 这样,在添加和更新主题时将无需重新编译和重新部署应用程序。 可以使用 pack URI 来标识和加载这些资源字典,如下面的示例所示。

 
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml">
<Application.Resources>
<ResourceDictionary Source="pack://siteoforigin:,,,/PageTheme.xaml" />
</Application.Resources>
</Application>

有关 WPF 中主题的概述,请参见样式设置和模板化

WPF 中的 Pack URI地(资源文件加载)的更多相关文章

  1. WTL中GDI+支持资源文件加载

    WTL中GDI+支持资源文件加载 分类: WTL WTL gdi+ gdi+2013-04-22 17:16 78人阅读 评论(0) 收藏 举报 WTLGDI+c++ 今天遇到一个小问题困扰了.就是G ...

  2. 在IIS上新发布的网站,样式与js资源文件加载不到(资源文件和网页同一个域名下)

    在IIS上新发布的网站,网站能打开,但样式与js资源文件加载不到(资源文件和网页是同一个域名下,例如:网页www.xxx.com/index.aspx,图片www.xxx.com/pic.png). ...

  3. 当Django设置DEBUG为False时,发现admin和html的静态资源文件加载失败的解决办法

    当Django设置DEBUG为False时,发现admin和html的静态资源文件加载失败,折腾一段时间终于找到解决办法: 1.先在setting文件增加BASE_DIR(项目的路径) BASE_DI ...

  4. WPF中的Pack URI

    更多资源:http://denghejun.github.io 问题 说来也简单:首先,我在WPF项目中建立了一个用户自定义控件(CustomControl),VS模板为我们自动生成了 CustomC ...

  5. 资源文件加载(Pack URI 方案)

    Pack URI 在 Windows Presentation Foundation (WPF) 中,使用统一资源标识符 (URI) 标识和加载文件的方式有很多,包括:1.指定当应用程序第一次启动时显 ...

  6. Java中的资源文件加载方式

    文件加载方式有两种: 使用文件系统自带的路径机制,一个应用程序只能有一个当前目录,但可以有Path变量来访问多个目录 使用ClassPath路径机制,类路径跟Path全局变量一样也是有多个值 在Jav ...

  7. qrc资源文件加载后,裸机环境下图片不显示

    问题描述:在qt开发环境下,使用qss进行界面美化工作,里面包含许多图片资源.最后项目决定把这些图片资源和代码一起打包.然后就把图片资源和qss文件一起编入qrc文件中进行编译.在本机开发环境下是没有 ...

  8. VC++ 使用WebBrowser控件中html文件以资源形式加载

    . . . . //加载资源文件中的HTML,IDR_HTML1就是HTML文件在资源文件中的ID wchar_t self_path[MAX_PATH] = { }; GetModuleFileNa ...

  9. 在.NET中读取嵌入和使用资源文件的方法

    转http://www.jb51.net/article/84660.htm 本文分别介绍了使用GetManifestResourceStream读取嵌入资源,和使用. resx资源文件嵌入资源,希望 ...

随机推荐

  1. 制作Visual Studio 2017 (VS 2017) 离线安装包

    史上功能最强大的Visual Studio 2017版本发布,但是由于版本更新速度加快和与第三方工具包集成的原因,微软研发团队没有为这个版本提供离线下载的安装文件.如果用户处在一个与外网隔离的网络环境 ...

  2. 201521123104 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点 1.2 可选:使用常规方法总结其他上课内容. 1.接口不是类,不能使用new进行实例化; 2.接口可以扩展; 3.接口中可以包含 ...

  3. ★★★★[转载]Python学习笔记一:数据类型转换★★★★

    一.int函数能够     (1)把符合数学格式的数字型字符串转换成整数     (2)把浮点数转换成整数,但是只是简单的取整,而非四舍五入. 举例: 1 aa = int("124&quo ...

  4. 201521123010 《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...

  5. Java课程设计博客(个人)

    Java课程设计博客(个人) 1. 团队课程设计博客链接 http://www.cnblogs.com/wkfg/p/7063081.html 2. 个人负责模块或任务说明 负责模块/任务:编写doG ...

  6. 201521123059 《Java程序设计》第十一周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 1.实现线程有两种方法:实现Ruannable接口和继承Thread类: 2.使用线程的start()方法启动线程 ...

  7. 生成/etc/shadow文件中的密码

    shadow文件的格式就不说了.就说说它的第二列--密码列. 通常,passwd直接为用户指定密码就ok了.但在某些情况下,要为待创建的用户事先指定密码,还要求是加密后的密码,例如kickstart文 ...

  8. Linux第二篇【系统环境、常用命令、SSH连接、安装开发环境】

    系统环境 我们知道Windows的出色就在于它的图形界面那一块,而Linux对图形界面的支持并不是那么友好-其实我们在Windows下对图形界面进行的操作都是得装换成命令的方式的! 当然了,我们在Ub ...

  9. WEB前端面试真题 - 2000!大数的阶乘如何计算?

    HTML5学堂-码匠:求某个数字的阶乘,很难吗?看上去这道题异常简单,却不曾想里面暗藏杀机,让不少前端面试的英雄好汉折戟沉沙. 面试真题题目 如何求"大数"的阶乘(如1000的阶乘 ...

  10. 如何用一天时间实现自己的RPC框架

    前言 最近,闲来无事,自己写了一个简单的RPC框架,我把它叫做SimpleRpc.它有多简单?一共只有1400行代码.这个RPC只是作为自己试验作品,交流技术之用,当然如果你敢用,也可以放到生产环境之 ...