WPF的资源引用大致有下面几个点需要讨论,下面我们逐个讨论。
目录
在WPF中统一资源标识符用于通过多种方式标识和方式加载文件,例如
- 加载图片
- 导航到指定页
- 架子车数据文件
- 指定初始化页
另外,他还可以用来标识文件的存储位置,例如
- 当前程序集
- 引用程序集
- 相对于程序集的某个位置
- 用硬车光绪的源站点
为了提供一整套方案,WPF使用了 Pack Uri方案。
Pack Uri方案
众所周知,一般我们使用的URI路径标识方案是以http、Ftp、file开头的(前缀),我们这里讲的Pack Uri方案不使用这些,统一使用pack作为其前缀,所以我们的路径就是类似于这样 pack://机构/路径。
机构,标识部件的包类型。
路径,标识部件在包中的位置。
一个包中一个存放一个或多个文件,例如
- 编译在本地程序集的资源文件
- 编译到所引用的程序集内的资源文件
- 编译到引用程序集内的资源文件
- 内容文件
- 源站点文件
访问这些文件,WPF支持俩种方式。
- application:///
- siteiforigin:///
application:/// 用来标识在编译时已知的应用程序数据文件,包括资源文件和内容文件。
siteiforigin:/// 用来标识源站点文件。
具体关于 URI的格式可以参考标准RFC2396
下面的图片说明具体的关系
资源文件Pack Uri
本地程序集资源
所谓资源文件是指将文件配置为Resource,MSBuild 之后编为程序集。资源文件可以在当前程序集也可以引用程序集。
编译到当前程序集的资源文件访问格式如下 授权;,,,/路径
- 授权:application:///
- 路径 资源文件的名称,包括其相对于本地程序集的文件夹根目录的路径。
下面的演示Pack Uri路径为资源文件在当前文件夹。
pack://application:,,,/ResourceFile.xaml
下面的演示Pack Uri路径为资源文件在当前文件夹下的子文件夹下。
pack://application:,,,/SubFolder/ResourceFile.xaml
引用程序集资源
引用程序集资源路径相对于本地程序集复杂一点,格式如下
程序集短名称{;版本}{;公钥};组件/路径
- 程序集短名称:所引用程序集的短名称
- ;版本[可选]:程序集版本信息,在加载多个具有相同名称的引用程序集时使用。
- ;公钥[可选]:相对应用程序集的签名的公钥。在加载多个具有相同名称的引用程序集时使用。
- ;组件:指定当前程序集所引用的程序集名称
- /路径:资源文件名称,如果存在于子文件夹中,那么这里也需要包含子文件夹。
上面的符号均为英文字符,不排除键入错误的可能
下面的演示Pack Uri路径为资源文件在当前文件夹。
pack://application:,,,ReferencedAssembly;component/ResourceFile.xaml
下面的演示Pack Uri路径为资源文件在当前文件夹下的子文件夹下。
pack://application:,,,ReferencedAssembly;component/SubFolder/ResourceFile.xaml
当要指定特定版本时
pack://application:,,,ReferencedAssembly;v1.0.0.1;component/SubFolder/ResourceFile.xaml
这种带版本的方式不建议使用,在实际使用非常容易导致资源文件找不到。(程序集版本可能被其他人误升级)
以下格式WPF 时不支持的
pack://siteoforgin:,,,ReferencedAssembly;component/SubFolder/ResourceFile.xaml
内容文件 Pack Uri
内容文件和资源文件的格式非常类似,格式如下授权,,,/路径
下面的演示Pack Uri路径为内容文件与当前程序集在同意文件夹中。
pack://application:,,,/ContentFile.xaml
下面的演示Pack Uri路径为内容文件在当前程序集的子文件夹下
pack://application:,,,/SubFolder/ContentFile.xaml
源站点 Pack Uri
源站点文件的pack Uri路径格式授权,,,/路径
- 授权:siteoforgin:///
- 路径:源站点文件的可执行程序集启动位置的路径
下面示例指在启动程序集所在文件夹
pack://siteoforgin:,,,/SiteOfOrginFile.xaml
下面的示例指在程序集所在文件夹的子文件夹下
pack://siteoforgin:,,,/SubFolder/SiteOfOrginFile.xaml
页面文件
指将一个xaml页面文件识别为页面类文件。否则这个这个文件(一般为*.xaml.cs和*.xaml俩个文件)无法识别为类,被程序直接使用
一个xaml通常需要继承自以下根元素
- System.Windows.Window
- System.Windows.Controls.Page
- System.Windows.Navigation.PageFuction<T>
- System.Windows.ResourceDictionary
- System.Windows.Documents.FlowDocument
- System.Windows.Contriols.UserControl
绝对和相对Pack Uri
我们前面介绍的都是绝对包Uri。在同一个程序集中当绝对路径为
pack://application:,,,/ResourceFile.xaml
其相对引用方式为
/ResourceFile.xaml
当有如下文件夹
App.xaml
Page2.xaml
\SubFolder\Page1.xaml
\SUbFolder\Page2.xaml
当Page2要引用Page1时,则可以直接使用/Page1.xam,页可以使用/SubFolder/Page1.xaml,也可以直接使用绝对包引用方式。
PackUri解析
Pack Uri使得不同的类型的文件包Uri看起来很相同,
为了探测Pack uri的引用文件类型,WPF 依照如下如下方法探测文件类型。
探测与pack URI匹配的属性的程序集元数据
AssmeblyAssociatedContentFileAttribute
如果找到该特性,则找到一个内容文件,如果找不到则探测编译到本地程序集的资源文件,如果找到与包URI路径匹配的资源文件,则包URI引用资源文件,否则包URI无效。
- URI包解析不适用场景
- 引用程序集的内容文件
- 应用程序集的嵌入文件
- 源站点文件
使用 PackUri 编程
许多类支持使用packURI设置属性,例如
- Application.StartUpUri
- Frame.Source
- NavigationWindow.Source
- Hyperlink.NavigateUri
- Window.Icon
- Image.Source
在标记中使用PackUri
绝对URI
文件 | 绝对包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,2;component/SubFolder/ResourceFile.xaml |
内容文件 | pack://application:,,,/ContentFile.xaml |
内容文件-子文件夹 | pack://application:,,,/SubFolder/ContentFile.xaml |
源站点文件 | pack://siteoforigin:,,,/S00File.xaml |
源站点文件-子文件夹 | pack://siteoforigin:,,,/SubFolder/S00File.xaml |
相对URI
文件 | 相对PackUri |
---|---|
本地程序集内的资源访问 | /ResourceFile.xaml |
本地程序集内的资源访问-子文件夹 | /SubFolder/ResourceFile.xaml |
引用程序集内的资源访问 | /ReferencedAssembly;component/ResourceFile.xaml |
引用程序集内的资源访问-子文件夹 | /ReferencedAssembly;component/SubFolder/ResourceFile.xaml |
内容文件 | /ContentFile.xaml |
内容文件-子文件夹 | /SubFolder/ContentFile.xaml |
代码中使用PackUri
默认情况下,Uri的构造器使用的使用的是绝对路径方式,所以下面的代码是正确的
Uri uri=new Uri("pack://application:,,,/File.xaml");
下面的代码是错误的
Uri uri=new Uri("/File.xaml");
所以当要使用相对路径时怎么使用呢?示例如下,下面俩种写法都是正确的
//绝对路径
Uri absoluteUri=new Uri("pack://application:,,,File.xaml",UriKind.Absolute);
//相对路径
Uri relativeUri=new Uri("/File.xaml",UriKind.Relative);
当你不清楚传入的PackUri地址是绝对的还是相对的时候,请直接使用RelativeOrAbsolute
TextBox box=new TextBox();
var uri=new Uri(box.Text,UriKind.RelativeOrAbsolute);
关于PackUrine 在代码中的引用总体和xaml种类似,你只要记住,uri默认单参构造器使用的是Absolute,当你搞不清楚使用的是相对uri还是绝对uri时,请使用RelativeOrAbsolute。
常见PackUri方案
指定应用程序MainWindow
StartUpUri用来指定WPF应用程序要显示的第一个窗口。对于独立应用程序,UI可以是一个窗口。见下面的示例代码
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" StartUri="MainWindow.xaml" />
导航到页面
下面的代码颜色如何导航到页面
<Page xmlns="http://......." WindowTitle="Page With HyperLink" WindowWidth="250" WindowHeight="250" />
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml" > Navigate To Another Page</Hyperlink>
指定窗口图标
<Window xmlns="http://schemas.microsoft.com....." Icon="WpfIcon.ico" />
上面Icon使用的路径为相对路径方式,你可以将icon MSbuild为Resource也可以是Content。从前面的讲解可知道他们的写法是一样的。
加载图像、音频和视频文件
<MediaElement Stretch="Fill" LoadBehavior="Play" Source="pack://siteoforigin:,,,/Media/bee.wmv"/>
<Image Source="Images/Watermark.png"/>
加载资源字典
WPF支持从外部加载主题样式,这样当更新或添加主题时就不需要重新编译程序了
<Application StartUri="HomePage.xaml" xmlns="http://schemas.microsoft.com/winfx/2006/presentation">
<Applitation.Resources>
<ResourceDictionary Source="pack://siteoforigin:,,,/PageTheme.xaml" />
</Applitation.Resources>
</Application>