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

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

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

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

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

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

Для ссылки на файлы данных приложения, в Windows Presentation Foundation (WPF) используется схема URI типа «Pack», подробно описываемая в разделе URI типа «Pack» в 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 типа «pack», который идентифицирует нужный файл ресурсов. 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 непосредственно в 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 типа "pack", включая окна, страницы, потоковые документы и словари ресурсов. Например, можно задать свойство Application.StartupUri с помощью URI типа "pack", который ссылается на окно или страницу для загрузки при запуске приложения.

<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 компилируется в сборку, а не в двоичную версию необработанного XAML.

Файлы с содержимым

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

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

Настройка файлов содержимого

Чтобы добавить файл содержимого в проект, файл данных приложения должен быть включен в качестве элемента Content. Кроме того, так как файл содержимого не компилируется непосредственно в сборку, необходимо задать элемент метаданных CopyToOutputDirectory MSBuild, чтобы указать, что этот файл содержимого копируется в местоположение, имеющее отношение к сборке построения. Если необходимо, чтобы ресурс копировался в папку выходных данных построения каждый раз, когда создается проект, настройте элемент метаданных 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 типа «pack», который идентифицирует нужный файл содержимого. 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:///, так как последнее требует разработки полного пути к файлу.

Примечание.

Файлы исходного узла не кэшируются браузерным приложением XAML (XBAP) на клиентском компьютере, в отличие от файлов содержимого. Следовательно, они загружаются только по специальному запросу. Если браузерное приложение XAML (XBAP) содержит большие мультимедийные файлы, их настройка в качестве файлов исходного узла означает, что первоначальный запуск приложения выполняется намного быстрее, а файлы загружаются только по требованию.

Настройка файлов исходного узла

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

Если во время компиляции известны файлы, которые должны быть расположены на исходном узле, но все еще требуется избежать явных зависимостей, можно добавить эти файлы в проект MSBuild в качестве элемента None. Как и для файлов содержимого, необходимо задать атрибут CopyToOutputDirectory MSBuild, чтобы указать, что файл исходного узла копируется в расположение относительно сборки построения, указывая либо значение 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, передав URI типа «pack», который идентифицирует нужный сайт исходного файла. GetRemoteStream возвращает объект StreamResourceInfo, который предоставляет сайт исходного файла в виде Stream и описывает его тип содержимого.

Например, в следующем коде показан способ использования GetRemoteStream для загрузки сайта исходного файла Page и установки его в качестве содержимого 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" />

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

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

См. также