URI типа "pack" в WPF

В Windows Presentation Foundation (WPF) универсальные идентификаторы ресурсов (URI) используются для идентификации и загрузки файлов различными способами, включая следующие:

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

  • Загрузка изображений.

  • Переход по страницам.

  • Загрузка неисполняемых файлов данных.

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

  • Текущая сборка.

  • Указанная ссылками сборка.

  • Расположение, связанное со сборкой.

  • Исходный узел приложения.

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

Схема URI типа "pack"

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

Package and Parts diagram

Для определения элементов в спецификации OPC используется расширяемость RFC 2396 (универсальные коды ресурса (URI): общий синтаксис) для определения схемы URI типа "pack".

Схема, которая задается с помощью URI, определяется его префиксом. Примеры — http, ftp и file. Схема URI рассматриваемого типа использует "pack" и содержит два компонента: центр и путь. Для URI типа "pack" используется следующий формат.

pack://центр/путь

Центр указывает тип пакета, в котором находится элемент, а путь — расположение элемента внутри пакета.

Эта концепция показана на следующей схеме:

Relationship among package, authority, and path

Пакеты и элементы аналогичны приложениям и файлам. Приложение (пакет) может содержать один или несколько файлов (элементов), в том числе:

  • Файлы ресурсов, скомпилированные в локальную сборку.

  • Файлы ресурсов, скомпилированные в сборку, на которую указывает ссылка.

  • Файлы ресурсов, скомпилированные в ссылающуюся сборку.

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

  • Файлы исходного узла.

Для доступа к этим типам файлов WPF поддерживает два центра: application:/// и siteoforigin:///. Центр application:/// определяет файлы данных приложения, известные во время компиляции, включая файлы ресурсов и файлы содержимого. Центр siteoforigin:/// определяет файлы исходного узла. На следующем рисунке показана область каждого центра.

Pack URI diagram

Примечание.

Компонент центра URI типа "pack" является встроенным URI, который указывает на пакет и должен соответствовать стандарту RFC 2396. Кроме того, символ "/" необходимо заменить символом ",", и необходимо обособлять escape-символами такие зарезервированные символы, как "%" и "?". Подробные сведения см. в OPC.

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

URI типа "pack" для файла ресурсов

Файлы ресурсов настраиваются как элементы Resource MSBuild и компилируются в сборки. WPF поддерживает формирование URI типа "pack", который можно использовать для идентификации файлов ресурсов, скомпилированных в локальную сборку или в сборку, на которую ссылается локальная сборка.

Файл ресурсов локальной сборки

URI типа "pack" для файла ресурсов, который компилируется в локальную сборку, использует следующие центр и путь:

  • Центр: application:///.

  • Путь: имя файла ресурсов, включая его путь относительно корневой папки проекта локальной сборки.

В следующем примере показан URI типа "pack" для файла ресурсов XAML, который находится в корневой папке проекта локальной сборки.

pack://application:,,,/ResourceFile.xaml

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

pack://application:,,,/Subfolder/ResourceFile.xaml

Файл ресурсов указанной ссылками сборки

URI типа "pack" для файла ресурсов, который компилируется в указанную ссылками сборку, использует следующие центр и путь:

  • Центр: application:///.

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

    AssemblyShortName{;Version]{;PublicKey];component/Path

    • AssemblyShortName — краткое имя для указанной ссылками сборки.

    • ;Version [необязательно] — версия указанной ссылками сборки, которая содержит файл ресурсов. Используется при загрузке двух или более указанных ссылками сборок с одинаковым кратким именем.

    • ;PublicKey [необязательно]: открытый ключ, который использовался для подписи указанной ссылками сборки. Используется при загрузке двух или более указанных ссылками сборок с одинаковым кратким именем.

    • ;component: указывает, что на упоминаемую сборку ссылается локальная сборка.

    • /Path: имя файла ресурсов, включая его путь относительно корневой папки проекта указанной ссылками сборки.

В следующем примере показан URI типа "pack" для файла ресурсов XAML, который находится в корневой папке проекта указанной ссылками сборки.

pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml

В следующем примере показан URI типа "pack" для файла ресурсов XAML, который находится во вложенной папке проекта указанной ссылками сборки.

pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

В следующем примере показан URI типа "pack" для файла ресурсов XAML, который находится в корневой папке проекта указанной ссылками сборки конкретной версии.

pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/ResourceFile.xaml

Обратите внимание, что синтаксис URI типа "pack" для файлов ресурсов указанной ссылками сборки может использоваться только с центром application:///. Например, следующее не поддерживается в WPF.

pack://siteoforigin:,,,/SomeAssembly;component/ResourceFile.xaml

URI типа "pack" для файла содержимого

URI типа "pack" для файла содержимого использует следующие центр и путь:

  • Центр: application:///.

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

В следующем примере показан URI типа "pack" для файла содержимого XAML, расположенного в той же папке, в которой находится исполняемая сборка.

pack://application:,,,/ContentFile.xaml

В следующем примере показан URI типа "pack" для файла содержимого XAML, расположенного во вложенной папке относительно исполняемой сборки приложения.

pack://application:,,,/Subfolder/ContentFile.xaml

Примечание.

К файлам содержимого HTML невозможно перейти. Схема URI поддерживает переход только к тем файлам HTML, которые расположены в исходном узле.

URI типа "pack" исходного узла

URI типа "pack" для файла исходного узла использует следующие центр и путь:

  • Центр: siteoforigin:///.

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

В следующем примере показан URI типа "pack" для файла исходного узла XAML, хранящегося в расположении, из которого запускается исполняемая сборка.

pack://siteoforigin:,,,/SiteOfOriginFile.xaml

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

pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml

Файлы подкачки

Файлы XAML, которые настроены как элементы Page MSBuild, компилируются в сборки таким же образом, как и файлы ресурсов. Следовательно, элементы Page MSBuild можно определить с помощью URI типа "pack" для файлов ресурсов.

Типы файлов XAML, которые обычно настраиваются как элементы Page MSBuild, имеют один из следующих корневых элементов:

Абсолютные и относительные URI типа "pack"

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

Например, рассмотрим следующий абсолютный URI типа "pack" для файла ресурсов в локальной сборке.

pack://application:,,,/ResourceFile.xaml

Относительный URI типа "pack", ссылающийся на данный файл ресурсов, будет следующим.

/ResourceFile.xaml

Примечание.

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

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

App.xaml

Page2.xaml

\SubFolder

+ Page1.xaml

+ Page2.xaml

Если Page1.xaml содержит URI, ссылающийся на корень\подпапка\Page2.xaml, ссылка может использовать следующий относительный URI типа "pack".

Page2.xaml

Если Page1.xaml содержит URI, ссылающийся на корень\Page2.xaml, ссылка может использовать следующий относительный URI типа "pack".

/Page2.xaml

Разрешение URI типа "pack"

Благодаря своему формату URI типа "pack" для разных типов файлов могут выглядеть одинаково. Рассмотрим следующий пример абсолютного URI типа "pack".

pack://application:,,,/ResourceOrContentFile.xaml

Этот абсолютный URI типа "pack" может ссылаться на файл ресурсов в локальной сборке или файл содержимого. Аналогично и для следующего относительного URI.

/ResourceOrContentFile.xaml

Чтобы определить тип файла, к которому относится URI типа "pack", WPF разрешает URI для файлов ресурсов в локальных сборках и файлы содержимого с помощью следующих эвристических методов:

  1. Проверка метаданных сборки на наличие атрибута AssemblyAssociatedContentFileAttribute, соответствующего URI типа "pack".

  2. Если атрибут AssemblyAssociatedContentFileAttribute найден, путь URI типа "pack" относится к файлу содержимого.

  3. Если атрибут AssemblyAssociatedContentFileAttribute не найден, проверяются файлы ресурсов набора, которые скомпилированы в локальную сборку.

  4. Если найден файл ресурса, соответствующий пути URI типа "pack", путь URI типа "pack" относится к файлу ресурсов.

  5. Если ресурс не найден, созданный внутренне Uri неверен.

Разрешение URI не применяется для URI, которые ссылаются на следующее:

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

  • Внедренные файлы в указанных ссылками сборках: URI, которые идентифицируют их, являются уникальными, так как включают имя указанной ссылками сборки и суффикс ;component.

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

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

Программирование с использованием URI типа "pack"

Многие классы WPF реализуют свойства, которые могут быть заданы с помощью URI типа "pack", включая следующие:

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

Использование URI типа "pack" в разметке

URI типа "pack" задается в разметке путем настройки элемента атрибута с помощью URI типа "pack". Например:

<element attribute="pack://application:,,,/File.xaml" />

В таблице 1 показаны различные варианты абсолютных URI типа "pack", которые можно указывать в разметке.

Таблица 1. Абсолютные URI типа "pack" в разметке

Файл Абсолютный URI типа "pack"
Файл ресурсов — локальная сборка "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 показаны различные варианты относительных URI типа "pack", которые можно указывать в разметке.

Таблица 2. Относительные URI типа "pack" в разметке

Файл Относительные URI типа "pack"
Файл ресурсов в локальной сборке "/ResourceFile.xaml"
Файл ресурсов в подпапке — локальная сборка "/Subfolder/ResourceFile.xaml"
Файл ресурсов в указанной ссылками сборке "/ReferencedAssembly;component/ResourceFile.xaml"
Файл ресурсов в подпапке указанной ссылками сборки "/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
Файл содержимого "/ContentFile.xaml"
Файл содержимого в подпапке "/Subfolder/ContentFile.xaml"

Использование URI типа "pack" в коде

Для указания URI типа "pack" в коде создается экземпляр класса Uri, и URI типа "pack" передается в конструктор в качестве параметра. Это продемонстрировано в следующем примере.

Uri uri = new Uri("pack://application:,,,/File.xaml");

По умолчанию класс Uri считает URI типа "pack" абсолютными. Следовательно, возникает исключение, если экземпляр класса Uri создается с относительным URI типа "pack".

Uri uri = new Uri("/File.xaml");

К счастью, при перегрузке Uri(String, UriKind) конструктора класса Uri принимается параметр типа UriKind, что позволяет вам указать, является ли URI типа "pack" абсолютным или относительным.

// Absolute URI (default)
Uri absoluteUri = new Uri("pack://application:,,,/File.xaml", UriKind.Absolute);
// Relative URI
Uri relativeUri = new Uri("/File.xaml",
                        UriKind.Relative);

Следует указать только Absolute или Relative, если есть уверенность, что предоставленный URI типа "pack" является тем или другим. Если используется неизвестный URI типа "pack", например, если пользователь вводит URI типа "pack" во время выполнения, используйте 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 показаны различные варианты относительных URI типа "pack", которые можно указывать в коде с помощью System.Uri.

Таблица 3. Абсолютные URI типа "pack" в коде

Файл Абсолютный URI типа "pack"
Файл ресурсов — локальная сборка 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 показаны различные варианты относительных URI типа "pack", которые можно указывать в коде с помощью System.Uri.

Таблица 4. Относительные URI типа "pack" в коде

Файл Относительные URI типа "pack"
Файл ресурсов — локальная сборка 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);

Типичные сценарии URI типа "pack"

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

Указание пользовательского интерфейса для отображения при запуске приложения

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

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

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

<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 см. в статье Общие сведения о переходах.

Указание значка окна

В следующем примере показано использование 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 позволяет приложениям использовать самые разные типы мультимедиа, все из которых могут быть идентифицированы и загружены с помощью URI типа "pack", как показано в следующих примерах.

<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) можно использовать для поддержки тем приложений. Одним из способов создания тем и управления ими является создание нескольких тем в качестве словарей ресурсов, расположенных в исходном узле приложения. Это позволяет добавлять и обновлять темы без повторной компиляции и развертывания приложения. Словари ресурсов можно определить и загрузить с помощью URI типа "pack", как показано в следующем примере.

<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, см. в статье Стилизация и использование шаблонов.

См. также