WPF中的URI
在 Windows Presentation Foundation (WPF) 中,使用统一资源标识符 (URI) 标识和加载文件的方式有很多,包括:
指定当应用程序第一次启动时显示的用户界面 (UI)。
加载图像。
导航到页
加载不可执行的数据文件。
此外,可以使用 URI 标识和加载位于各种位置的文件,这些位置包括:
当前程序集。
所引用的程序集。
相对于程序集的某个位置。
应用程序的源站点。
为了提供从这些位置标识和加载上述类型的文件的一致机制,WPF 利用了 pack URI 方案的扩展性。本主题将概述这一方案,介绍如何为各种方案构造 pack URI,讨论绝对和相对 URI 以及 URI 解析,然后说明如何在标记和代码中使用 pack URI。
本主题包括下列各节。
- Pack URI 方案
- 资源文件 Pack URI
- 内容文件 Pack URI
- 源站点 Pack URI
- 页面文件
- 绝对与相对 Pack URI
- Pack 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:
探测与 pack URI 匹配的 AssemblyAssociatedContentFileAttribute 特性的程序集元数据。
如果找到 AssemblyAssociatedContentFileAttribute 特性,则 pack URI 的路径引用内容文件。
如果未找到 AssemblyAssociatedContentFileAttribute 特性,则探测编译到本地程序集中的资源文件集。
如果找到与 pack URI 的路径匹配的资源文件,则 pack URI 的路径引用资源文件。
如果未找到合适的资源,则内部创建的 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 中导航的各种方式的更多信息,请参见导航概述。
指定窗口图标
下面的示例演示如何使用 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 标识和加载,如下面的示例所示。
有关使用媒体内容的更多信息,请参见 图形和多媒体。
从源站点加载资源字典
可以使用资源字典 (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中的URI的更多相关文章
- WPF 中的 Pack URI地(资源文件加载)
参考资源网http://msdn.microsoft.com/zh-cn/library/aa970069.aspx#Absolute_vs_Relative_Pack_URIs 在 Windows ...
- WPF 中图片的加载 ,使用统一资源标识符 (URI)
在wpf中,设置图片路径有2种方法: 1.xaml文件中,指定路径 <Button Name=" HorizontalAlignment="Right" Verti ...
- WPF中UserControl和DataTemplate
最新更新: http://denghejun.github.io 前言 前言总是留给我说一些无关主题的言论,WPF作为全新Microsoft桌面或web应用程序显示技术框架, 从08年开始,一直到现在 ...
- WPF中的image控件的Source赋值
WPF中的Image控件Source的设置 1.XAML中 简单的方式(Source="haha.png"); image控件的Source设置为相对路径后(Source=&quo ...
- WPF中加载高分辨率图片性能优化
在最近的项目中,遇到一个关于WPF中同时加载多张图片时,内存占用非常高的问题. 问题背景: 在一个ListView中同时加载多张图片,注意:我们需要加载的图片分辨率非常高. 代码: XAML: < ...
- WPF中资源引用方式汇总
在WPF应用程序开发中,总是难以记住各种访问资源的方法,遂逐一记下. 先从资源是否编译到程序集分类 一.程序集资源 资源在编译的时候嵌入到程序集中.WPF中的XAML会被编译为BAML,图片等其他资源 ...
- Unity3D 将 Unity 嵌入WPF中的一些研究笔记
一. 在 WPF 中使用 WebBrowser,直接打开 WebPlayer.html 以这种方式有一个问题是. 无法在 WebBrowser 的上面 放置其它的控件, 在运行时,都不会显示 . 以 ...
- WPF中Image控件绑定到自定义类属性
首先我们定义一个Student类,有ID,Name,Photo(保存图片路径). using System; using System.Collections.Generic; using Syste ...
- WPF中通过代码定义模板
WPF中可以再XAML中定义模板,也可以通过C#代码定义模板,通过代码可能更清楚的看清其逻辑,而且代码的好处就是可以随时动态的去操作,而在XAML中定义的一般都是静态的. //控件呈现的显示内容1(这 ...
随机推荐
- 12 new方法和单例、定制访问函数、装饰器
new方法和单例.定制访问函数.装饰器 上节课作业解答 # 通过多重继承方法,分别定义出动物,人类,和和荷兰人三种类 class Animal(object): def __init__(self, ...
- python基础之面向对象编程介绍、类和对象
面向对象变成介绍 面向过程编程 核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西.主要应用在一旦完成很少修改的地方,如linux ...
- Android面试收集录4 Fragment详解
1.什么是Fragment? 你可以简单的理解为,Fragment是显示在Activity中的Activity. 它可以显示在Activity中,然后它也可以显示出一些内容. 因为它拥有自己的生命周期 ...
- Android 自定义光标样式
今天自定义光标,自己切图,不过怎么切都是很宽.不是一个很细的条.我用ps花了一个像素的直线,放上去还是不行.后来在网上找到方法,那就是用shape.不得不说,shape真的是太吊了. 给EditTex ...
- Android 布局开发之百分比布局、弹性布局
1.百分比布局 很简单,超级简单.引用之后就可以使用了. compile 'com.android.support:percent:23+' git地址: https://github.com/Jul ...
- hbase shell出现ERROR:Can't get master address from Zookeeper;znode data==null
hbase shell出现ERROR:Can't get master address from Zookeeper;znode data==null(ERROR:org.apache.hadoop. ...
- groupSum6后向遍历
http://codingbat.com/prob/p199368 public boolean groupSum6(int start, int[] nums, int target) { if( ...
- http客户端缓存
这篇文章写得比较,点击查看
- mac虚拟机上(centos系统)设置联网第二种方式
这种方式简单,不容易出错,用的桥接的方式. 这样的安装的centos会得到ip地址 然后编辑一下网卡配置,使其变为静态得ip 输入命令 # vi /etc/sysconfig/network-scri ...
- CodeForces-1061D TV Shows
题目链接 https://vjudge.net/problem/CodeForces-1061D 题面 Description There are nn TV shows you want to wa ...