WPF 應用程式資源、內容和資料檔案
Microsoft Windows 應用程式通常取決於包含非可執行資料的檔案,例如 Extensible Application Markup Language (XAML)、影像、視訊和音訊。 Windows Presentation Foundation (WPF) 提供特殊支援,可用來設定、識別和使用這些類型的資料檔案,這些檔案稱為應用程式資料檔案。 這項支援是以一組特定的應用程式資料檔案類型為中心,包括:
資源檔 :編譯成可執行檔或程式庫 WPF 元件的資料檔案。
內容檔 :與可執行 WPF 元件有明確關聯的獨立資料檔案。
原始檔案 月臺:與可執行 WPF 元件沒有關聯的獨立資料檔案。
這三種檔案類型之間的其中一個重要區別是資源檔和內容檔是建置階段的已知檔案;組件並明確知道這兩種檔案。 不過,對於源檔案網站,元件可能完全不知道這些檔案,或透過套件統一資源識別項 (URI) 參考隱含知識;後者的情況,不保證參考的原始程式檔網站確實存在。
為了參考應用程式資料檔案,Windows Presentation Foundation (WPF) 會使用套件統一資源識別項 (URI) 配置,如 WPF 中的 套件 URI 中所述。
本主題描述何設定及使用應用程式資料檔案。
資源檔
若應用程式資料檔案必須一律可供應用程式使用,確保可用性的唯一方法是將檔案編譯成應用程式的主要可執行檔組件或是應用程式的其中一個參考組件。 這種類型的應用程式資料檔案稱為「資源檔」。
應該使用資源檔的時機包括:
您不需要在資源檔編譯成組件之後更新該檔案的內容。
您想要透過減少檔案相依性數目的方式,簡化複雜的應用程式發佈程序。
您的應用程式資料檔案必須可以當地語系化 (請參閱 WPF 全球化和當地語系化概觀)。
注意
本節所述的資源檔與 XAML 資源 中所述的資源檔不同,與管理應用程式資源 (.NET) 中所述 的內嵌或連結資源不同。
設定資源檔
在 WPF 中,資源檔是包含在 Microsoft 組建引擎 (MSBuild) 專案中作為 Resource
專案的檔案。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Resource Include="ResourceFile.xaml" />
</ItemGroup>
...
</Project>
注意
在 Visual Studio 中,您會將檔案新增至專案,並將其設定 Build Action
Resource
為 ,以建立資源檔。
建置專案時,MSBuild 會將資源編譯成元件。
使用資源檔
若要載入資源檔,您可以呼叫 GetResourceStream 類別的 Application 方法,傳遞識別所需資源檔的套件 URI。 GetResourceStream 會傳 StreamResourceInfo 回 物件,此物件會將資源檔公開為 Stream ,並描述其內容類型。
例如,下列程式碼示範如何使用 GetResourceStream 來載入 Page 資源檔,並將其設定為 Frame ( pageFrame
):
// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetResourceStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page
GetResourceStream呼叫 時,可讓您存取 Stream ,您必須執行將它轉換成您要設定之屬性類型的額外工作。 相反地,您可以讓 WPF 使用程式碼,直接將資源檔載入至型別的 屬性,以負責開啟和轉換 Stream 。
下列範例示範如何使用程式碼直接載入 Page ( FramepageFrame
)。
Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
下列範例相當於前一個範例的標記對等用法。
<Frame Name="pageFrame" Source="PageResourceFile.xaml" />
應用程式程式碼檔案作為資源檔
您可以使用套件 URI 來參考一組特殊的 WPF 應用程式程式碼檔案,包括視窗、頁面、流程檔和資源字典。 例如,您可以使用參考應用程式啟動時所要載入之視窗或頁面的套件 URI 來設定 Application.StartupUri 屬性。
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="SOOPage.xaml" />
當 XAML 檔案以專案的形式包含在 MSBuild 專案中 Page
時,您可以執行此動作。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Page Include="MainWindow.xaml" />
</ItemGroup>
...
</Project>
注意
在 Visual Studio 中,您會將新的 Window 、 NavigationWindow 、 PageFlowDocument 或 ResourceDictionary 新增至專案, Build Action
標記檔案的 會預設為 Page
。
編譯具有 Page
專案的專案時,XAML 專案會轉換成二進位格式,並編譯成相關聯的元件。 因此,這些檔案可以比照一般資源檔的方式來使用。
注意
如果 XAML 檔案設定為 Resource
專案,而且沒有程式碼後置檔案,原始 XAML 會編譯成元件,而不是原始 XAML 的二進位版本。
內容檔
「內容檔」是以鬆散檔案的形式連同可執行檔組件一併發佈。 雖然這種檔案並未編譯成組件,但是編譯組件時使用的中繼資料會建立與每個內容檔的關聯。
如果應用程式需要一組特定的應用程式資料檔案,而您不想在更新這些檔案時重新編譯使用它們的組件,您應該使用內容檔。
設定內容檔
若要將內容檔新增至專案,應用程式資料檔案必須包含為 Content
專案。 此外,由於內容檔未直接編譯到元件中,因此您必須設定 MSBuild CopyToOutputDirectory
中繼資料元素,以指定內容檔案會複製到相對於建置元件的位置。 如果您想要在每次建置專案時將資源複製到組建輸出檔案夾,請使用 值來設定 CopyToOutputDirectory
中繼資料元素 Always
。 否則,您可以使用 值,確保只有最新版本的資源會複製到組建輸出檔案夾 PreserveNewest
。
以下顯示設定為內容檔的檔案;只有在將新版本的資源新增至專案時,這個內容檔才會複製到建置輸出資料夾。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Content Include="ContentFile.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
...
</Project>
注意
在 Visual Studio 中,您會將檔案新增至專案,並將其設定為 ,並將其設定為 ,並將它 Build Action
Copy to Output Directory
Copy always
Content
設定為 (相同 Always
) 和 Copy if newer
(與 PreserveNewest
相同) 來建立內容檔案。
建置專案時, AssemblyAssociatedContentFileAttribute 屬性會編譯成每個內容檔案之元件的中繼資料。
[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]
的值 AssemblyAssociatedContentFileAttribute 表示內容檔的路徑相對於其在專案中的位置。 例如,如果內容檔位於專案子資料夾中,則會將其他路徑資訊併入 AssemblyAssociatedContentFileAttribute 值。
[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]
此值 AssemblyAssociatedContentFileAttribute 也是建置輸出檔案夾中內容檔案路徑的值。
使用內容檔
若要載入內容檔案,您可以呼叫 GetContentStream 類別的 Application 方法,傳遞識別所需內容檔案的套件 URI。 GetContentStream 會傳 StreamResourceInfo 回 物件,此物件會將內容檔公開為 Stream ,並描述其內容類型。
例如,下列程式碼示範如何使用 GetContentStream 來載入 Page 內容檔案,並將其設定為 ( pageFrame
) 的內容 Frame 。
// Navigate to xaml page
Uri uri = new Uri("/PageContentFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetContentStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetContentStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page
GetContentStream呼叫 時,可讓您存取 Stream ,您必須執行將它轉換成您要設定之屬性類型的額外工作。 相反地,您可以讓 WPF 使用程式碼,直接將資源檔載入至型別的 屬性,以負責開啟和轉換 Stream 。
下列範例示範如何使用程式碼直接載入 Page ( FramepageFrame
)。
Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
下列範例相當於前一個範例的標記對等用法。
<Frame Name="pageFrame" Source="PageContentFile.xaml" />
來源網站檔
資源檔與元件有明確的關聯性,這些元件會和 一起散發,如 所 AssemblyAssociatedContentFileAttribute 定義。 但是在某些情況下,您可能想在組件和應用程式資料檔案之間建立隱含或不存在的關聯性,這些情況包括:
編譯時期不存在檔案。
在執行階段之前,您不知道組件需要哪些檔案。
您不想在更新檔案時重新編譯其關聯的組件。
應用程式使用大型的資料檔案,例如音訊和視訊,而您只想讓使用者自行選擇是否下載這些檔案。
您可以使用傳統 URI 配置來載入這些類型的檔案,例如 file:///
和 http://
配置。
<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />
不過, file:///
和 http://
配置需要您的應用程式具有完全信任。 如果您的應用程式是從網際網路或內部網路啟動的 XAML 瀏覽器應用程式 (XBAP),而且只會要求從這些位置啟動的應用程式允許的許可權集,則鬆散檔案只能從應用程式的原點 (啟動位置) 載入。 這類檔案稱為「來源網站」檔。
來源網站檔是部分信任應用程式的唯一選擇,但並不是只適用於部分信任應用程式。 完全信任應用程式可能還是需要載入它們在建置階段並不知道的應用程式資料檔案;雖然完全信任應用程式可以使用 file:///,但是應用程式資料檔案可能會安裝在應用程式組件的相同資料夾或子資料夾中。 在此情況下,使用來源網站參考比使用 file:/// 簡單,因為使用 file:/// 時,您必須找出檔案的完整路徑。
注意
來源檔案的網站不會在用戶端電腦上使用 XAML 瀏覽器應用程式 (XBAP) 快取,而內容檔案則為 。 因此,只有在特別要求時,才會下載來源網站檔。 如果 XAML 瀏覽器應用程式 (XBAP) 應用程式有大型媒體檔案,請將它們設定為原始程式檔的月臺表示初始應用程式啟動速度會快得多,而且檔案只會視需要下載。
設定來源網站檔
如果您的原點檔案在編譯時期不存在或未知,您必須使用傳統的部署機制,以確保執行時間可以使用所需的檔案,包括使用 XCopy
命令列程式或 Microsoft Windows Installer。
如果您在編譯階段知道您想要位於原點的檔案,但仍想要避免明確的相依性,您可以將這些檔案新增至 MSBuild 專案做為 None
專案。 如同內容檔,您必須設定 MSBuild CopyToOutputDirectory
屬性,藉由指定 Always
值或 PreserveNewest
值,將源檔案的月臺複製到相對於建置元件的位置。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<None Include="PageSiteOfOriginFile.xaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
...
</Project>
注意
在 Visual Studio 中,您會將檔案新增至專案,並將其設定 Build Action
None
為 ,以建立源檔案網站。
建置專案時,MSBuild 會將指定的檔案複製到組建輸出檔案夾。
使用來源網站檔
若要載入源檔案的月臺,您可以呼叫 GetRemoteStream 類別的 Application 方法,傳遞識別源檔案所需月臺的 Pack URI。 GetRemoteStream 會傳 StreamResourceInfo 回 物件,此物件會將源檔案的網站公開為 Stream ,並描述其內容類型。
例如,下列程式碼示範如何使用 GetRemoteStream 載入 Page 源檔案網站,並將其設定為 ( pageFrame
) 的內容 Frame 。
// Navigate to xaml page
Uri uri = new Uri("/SiteOfOriginFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetRemoteStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/SiteOfOriginFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetRemoteStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page
GetRemoteStream呼叫 時,可讓您存取 Stream ,您必須執行將它轉換成您要設定之屬性類型的額外工作。 相反地,您可以讓 WPF 使用程式碼,直接將資源檔載入至型別的 屬性,以負責開啟和轉換 Stream 。
下列範例示範如何使用程式碼直接載入 Page ( FramepageFrame
)。
Uri pageUri = new Uri("pack://siteoforigin:,,,/SiteOfOriginFile.xaml", UriKind.Absolute);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml", UriKind.Absolute)
Me.pageFrame.Source = pageUri
下列範例相當於前一個範例的標記對等用法。
<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
在變更組建類型之後重建
在變更應用程式資料檔案的組建類型之後,您必須重建整個應用程式,以確認套用這些變更。 若您只建置應用程式,則不會套用變更。
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應