參考資源網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
完全限定 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 中導航的各種方式的更多信息,請參見導航概述。
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 中主題的概述,請參見樣式設置和模板化。