Поделиться через


Ресурс приложения WPF, содержимое и файлы данных

Приложения Microsoft Windows часто зависят от файлов, содержащих не исполняемые данные, такие как язык разметки приложений (XAML), изображения, видео и звук. Windows Presentation Foundation (WPF) предоставляет специальную поддержку для настройки, идентификации и использования этих типов файлов данных, которые называются файлами данных приложения. Эта поддержка вращается вокруг определенного набора типов файлов данных приложения, в том числе:

  • Файлы ресурсов: файлы данных, которые компилируются в исполняемую сборку или сборку библиотеки WPF.

  • Файлы содержимого: автономные файлы данных, имеющие явную связь с исполняемой сборкой WPF.

  • Сайт исходного файла: автономные файлы данных, не имеющие связи с исполняемой сборкой WPF.

Одним из важных различий между этими тремя типами файлов является то, что файлы ресурсов и файлы содержимого известны во время сборки; сборка имеет точные сведения о них. Однако для файлов сайта происхождения сборка может не иметь никаких знаний о них вообще или иметь неявные знания с помощью ссылки на универсальный идентификатор ресурса (URI) пакета; В последнем случае нет гарантии того, что указанный файл сайта происхождения действительно существует.

Для ссылки на файлы данных приложения Windows Presentation Foundation (WPF) использует схему универсального идентификатора ресурса (URI) пакета, которая подробно описана в URI пакета в WPF.

В этом разделе описывается настройка и использование файлов данных приложения.

Файлы ресурсов

Если файл данных приложения всегда должен быть доступен приложению, единственным способом обеспечения доступности является компиляция в основную исполняемую сборку приложения или одну из указанных на нее сборок. Этот тип файла данных приложения называется файлом ресурсов.

Файлы ресурсов следует использовать при:

  • Вам не нужно обновлять содержимое файла ресурса после его компиляции в сборку.

  • Необходимо упростить сложность распространения приложений, уменьшая количество зависимостей файлов.

  • Файл данных приложения должен быть локализуемым (см. обзор глобализации и локализации WPF).

Замечание

Файлы ресурсов, описанные в этом разделе, отличаются от файлов ресурсов, описанных в ресурсах XAML , и отличаются от внедренных или связанных ресурсов, описанных в разделе "Управление ресурсами приложений( .NET)".

Настройка файлов ресурсов

В WPF файл ресурсов — это файл, который входит в проект подсистемы сборки Майкрософт (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):

// 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 в Frame (pageFrame).

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" />

Файлы кода приложения в качестве файлов ресурсов

На специальный набор файлов кода приложения WPF можно ссылаться с помощью URI пакетов, включая окна, страницы, документы потока и словари ресурсов. Например, можно задать Application.StartupUri свойство с помощью URI пакета, ссылающегося на окно или страницу, которую вы хотите загрузить при запуске приложения.

<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, Page, FlowDocument или ResourceDictionary в проект, Build Action для файла разметки по умолчанию будет Page.

При компиляции проекта с Page элементами элементы XAML преобразуются в двоичный формат и компилируются в связанную сборку. Следовательно, эти файлы можно использовать так же, как и типичные файлы ресурсов.

Замечание

Если файл XAML настроен как элемент Resource, и у него нет связанного файла с кодом, то сырая версия 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 в Content, а Copy to Output Directory в Copy always (то же, что и 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 и задать его в качестве содержимого Frame (pageFrame).

// 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 в Frame (pageFrame).

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.

Если вы знаете во время компиляции файлы, которые вы хотите найти на сайте источника, но по-прежнему хотите избежать явной зависимости, вы можете добавить эти файлы в проект 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 и описывает его тип содержимого.

Например, в следующем коде показано, как загрузить файл источника GetRemoteStreamPage и установить его в качестве содержимого Frame (pageFrame).

// 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 в Frame (pageFrame).

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" />

Перестроение после изменения типа сборки

После изменения типа сборки файла данных приложения необходимо перестроить все приложение, чтобы убедиться, что эти изменения применяются. Если вы только создаёте приложение, изменения не применяются.

См. также