Использование ресурсов

98

Упакованные URI

WPF позволяет обращаться к скомпилированным ресурсам (вроде BAML-файла для страницы) с помощью синтаксиса упакованных URI (pack URI). В предыдущей статье в элементе Image и дескрипторе для ссылки на ресурс использовался относительный URI:

images/winter.jpg

Эквивалентный ему более громоздкий абсолютный URI показан ниже:

pack://application:,,,/images/winter.jpg

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

В случае применения абсолютного URI можно использовать путь к файлу, UNC-путь к сетевому ресурсу, URL-адрес веб-сайта или упакованный URI, указывающий на ресурс сборки. Главное помнить о том, что если приложению не удастся извлечь ресурс из указанного места, сгенерируется исключение. Если URI был установлен в XAML, исключение сгенерируется на этапе создания страницы.

Синтаксис упакованного URI был позаимствован из стандарта XPS (XML Paper Specification). Причина его странного внешнего вида заключается в том, что он подразумевает вставку одного URI внутрь другого. Три запятых фактически представляют собой три отмененных косых черты. Другими словами, показанный выше упакованный URI содержит URI приложения, начинающийся с конструкции application://.

Ресурсы в других сборках

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

pack://application:,,,/AssemblyName;component/ResourceName

Например, если изображение находится в ссылаемой сборке по имени ImageLibrary, потребуется использовать такой URI:

img.Source = new BitmapImage(
       new Uri("pack://application:,,,/ImageLibrary;component/images/winter.jpg"));

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

img.Source = new Bitmaplmage(
   new Uri("ImageLibrary;vl.25;dc642a7f5bd64912;component/images/winter.jpg",
   UnKind.Relative));

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

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

Звуковые классы WPF не поддерживают ресурсов сборки. По этой причине способа для извлечения аудиофайла из потока ресурсов и его воспроизведения не существует — по крайней мере, без его предварительного сохранения. Таково ограничение лежащих в основе технологии компонентов, на которых основаны данные классы (а именно — интерфейса Win32 API и проигрывателя Media Player).

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

Файлы содержимого в сборку не встраиваются. Тем не менее, WPF добавляет к сборке атрибут AssemblyAssociatedContentFile, который объявляет о существовании каждого файла содержимого. Этот атрибут также записывает информацию о размещении каждого файла содержимого по отношению к исполняемому файлу (показывая, находится ли файл содержимого в той же папке, что и исполняемый файл, или же в отдельной подпапке). Лучше всего то, что для использования файлов содержимого с элементами, умеющими работать с ресурсами, можно применять ту же самую систему URI.

Чтобы проверить это, добавьте в свой проект какой-то звуковой файл, выделите его в окне Solution Explorer и измените значение свойства Build Action в окне Properties на Content (содержимое). Удостоверьтесь в том, что для параметра Copy to Output Directory (Копировать в выходной каталог) установлено значение Copy Always (Копировать всегда), чтобы звуковой файл копировался в каталог вывода при компоновке проекта.

Теперь можно использовать относительный URI, чтобы указать MediaElement на свой файл содержимого:

<MediaElement Name="Sound" Source="Sounds/start.wav"
   LoadedBehavior="Manual"></MediaElement>
Пройди тесты
Лучший чат для C# программистов