Empaquetar URI en WPF

En Windows Presentation Foundation (WPF), los identificadores uniformes de recursos (URI) se usan para identificar y cargar archivos de muchas maneras, incluidas las siguientes:

  • Especificando la interfaz de usuario (IU) que se va a mostrar cuando una aplicación se inicia por primera vez.

  • Cargando imágenes.

  • Navegando a páginas.

  • Cargando archivos de datos no ejecutables.

Además, se pueden usar URI para identificar y cargar archivos desde varias ubicaciones, incluidas las siguientes:

  • Ensamblado actual.

  • El ensamblado al que se hace referencia.

  • Una ubicación relativa a un ensamblado.

  • El sitio de origen de la aplicación.

Para proporcionar un mecanismo coherente para identificar y cargar estos tipos de archivos desde estas ubicaciones, WPF aprovecha la extensibilidad del esquema Pack URI. En este tema se proporciona información general sobre el esquema, se describe cómo construir Pack URI para diversos escenarios, se explican los URI absolutos y relativos y la resolución de identificador URI antes de mostrar cómo usar los Pack URI, tanto desde el marcado como desde el código.

Esquema de Pack URI

El esquema de Pack URI se usa en la especificación de Convenciones de empaquetado abierto (OPC), que describe un modelo para organizar e identificar contenido. Los elementos clave de este modelo son los paquetes y los elementos, donde un paquete es un contenedor lógico para uno o varios elementos lógicos. La figura siguiente ilustra este concepto.

Diagrama de paquete y partes

Para identificar los elementos, la especificación de OPC aprovecha la extensibilidad de RFC 2396 (Identificadores uniformes de recursos [URI]: sintaxis genérica) para definir el esquema Pack URI.

El esquema especificado por un identificador URI se define por su prefijo; http, ftp y file son ejemplos conocidos. El esquema Pack URI usa "pack" como esquema y tiene dos componentes: la autoridad y la ruta de acceso. El siguiente es el formato de un Pack URI.

pack:// autoridad/ruta de acceso

La autoridad especifica el tipo de paquete que contiene una parte, mientras que la ruta de acceso especifica la ubicación de una parte dentro de un paquete.

Este concepto se muestra en la ilustración siguiente:

Relación entre paquete, autoridad y ruta de acceso

Los paquetes y los elementos son análogos a las aplicaciones y los archivos, donde una aplicación (paquete) puede incluir uno o más archivos (elementos), como los siguientes:

  • Archivos de recursos que se compilan en el ensamblado local.

  • Archivos de recursos que se compilan en un ensamblado al que se hace referencia.

  • Archivos de recursos que se compilan en un ensamblado que hace referencia.

  • Archivos de contenido.

  • Archivos de sitio de origen.

Para obtener acceso a estos tipos de archivos, WPF admite dos autoridades: application:/// y siteoforigin:///. La autoridad application:/// identifica los archivos de datos de aplicación que se conocen en tiempo de compilación, incluidos los archivos de recursos y de contenido. La autoridad siteoforigin:/// identifica los archivos de sitio de origen. El ámbito de cada autoridad se muestra en la figura siguiente.

Diagrama de URI de paquete

Nota

El componente de autoridad de un Pack URI es un identificador URI incrustado que apunta a un paquete y debe ajustarse a RFC 2396. Además, el carácter "/" se debe reemplazar por el carácter ",", y los caracteres reservados "%" y "?" deben incluirse en secuencias de escape. Consulte la especificación de OPC para detalles.

En las secciones siguientes se explica cómo construir Pack URI con estas dos autoridades junto con las rutas de acceso adecuadas para identificar los archivos de recursos, de contenido y de sitio de origen.

Pack URI de archivos de recursos

Los archivos de recursos están configurados como elementos Resource de MSBuild y se compilan en ensamblados. WPF admite la construcción de Pack URI que se pueden usar para identificar los archivos de recursos compilados en el ensamblado actual o compilados en un ensamblado al que se hace referencia desde el ensamblado local.

Archivo de recursos del ensamblado local

El Pack URI de un archivo de recursos compilado en el ensamblado local usa la siguiente autoridad y ruta de acceso:

  • Autoridad: application:///.

  • Ruta de acceso: nombre del archivo de recursos, incluida su ruta de acceso relativa a la carpeta raíz del proyecto de ensamblado local.

En el ejemplo siguiente se muestra el Pack URI de un archivo de recursos XAML que se encuentra en la raíz de la carpeta del proyecto del ensamblado local.

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

En el ejemplo siguiente se muestra el Pack URI de un archivo de recursos XAML que se encuentra en una subcarpeta de la carpeta del proyecto del ensamblado local.

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

Archivo de recursos del ensamblado al que se hace referencia

El Pack URI de un archivo de recursos compilado en un ensamblado al que se hace referencia usa la siguiente autoridad y ruta de acceso:

  • Autoridad: application:///.

  • Ruta de acceso: nombre de un archivo de recursos que se compila en un ensamblado al que se hace referencia. La ruta de acceso debe tener el formato siguiente:

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

    • AssemblyShortName: nombre corto del ensamblado al que se hace referencia.

    • ;Version [opcional]: versión del ensamblado al que se hace referencia y que contiene el archivo de recursos. Se usa cuando hay cargados dos o más ensamblados a los que se hace referencia con el mismo nombre corto.

    • ;PublicKey [opcional]: clave pública que se usó para firmar el ensamblado al que se hace referencia. Se usa cuando hay cargados dos o más ensamblados a los que se hace referencia con el mismo nombre corto.

    • ;component: especifica que la referencia al ensamblado se hace desde el ensamblado local.

    • /Path: nombre del archivo de recursos, incluida su ruta de acceso relativa a la raíz de la carpeta del proyecto del ensamblado al que se hace referencia.

En el ejemplo siguiente se muestra el Pack URI de un archivo de recursos XAML que se encuentra en la raíz de la carpeta del proyecto del ensamblado al que se hace referencia.

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

En el ejemplo siguiente se muestra el Pack URI de un archivo de recursos XAML que se encuentra en una subcarpeta de la carpeta del proyecto del ensamblado al que se hace referencia.

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

En el ejemplo siguiente se muestra el Pack URI de un archivo de recursos XAML que se encuentra en la carpeta raíz de la carpeta del proyecto de un ensamblado específico de la versión al que se hace referencia.

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

Tenga en cuenta que la sintaxis de Pack URI para los archivos de recursos del ensamblado al que se hace referencia solo se puede usar con la autoridad application:///. Por ejemplo, no se admite lo siguiente en WPF.

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

Pack URI de archivos de contenido

El Pack URI de un archivo de contenido usa la siguiente autoridad y ruta de acceso:

  • Autoridad: application:///.

  • Ruta de acceso: nombre del archivo de contenido, incluida su ruta de acceso relativa a la ubicación del sistema de archivos del ensamblado ejecutable principal de la aplicación.

En el ejemplo siguiente se muestra el Pack URI para un archivo de contenido XAML, ubicado en la misma carpeta que el ensamblado ejecutable.

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

En el ejemplo siguiente se muestra el Pack URI para un archivo de contenido XAML, ubicado en una subcarpeta relativa al ensamblado ejecutable de la aplicación.

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

Nota

No se puede navegar a los archivos de contenido HTML. El esquema de URI solo admite la navegación a archivos HTML ubicados en el sitio de origen.

Pack URI de sitio de origen

El Pack URI de un archivo de sitio de origen usa la siguiente autoridad y ruta de acceso:

  • Autoridad: siteoforigin:///.

  • Ruta de acceso: nombre del archivo de sitio de origen, incluida su ruta de acceso relativa a la ubicación desde donde se inició el ensamblado ejecutable.

En el ejemplo siguiente se muestra el Pack URI de un archivo de sitio de origen XAML, almacenado en la ubicación desde donde se inició el ensamblado ejecutable.

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

En el ejemplo siguiente se muestra el Pack URI de un archivo de sitio de origen XAML, almacenado en una subcarpeta relativa a la ubicación desde donde se inició el ensamblado ejecutable de la aplicación.

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

Archivos de paginación

Los archivos XAML que están configurados como elementos Page de MSBuild se compilan en ensamblados del mismo modo que los archivos de recursos. Por consiguiente, los elementos Page de MSBuild se pueden identificar mediante los Pack URI para los archivos de recursos.

Los tipos de archivo XAML que habitualmente se configuran como elementos Page de MSBuild tienen uno de los siguientes elementos como elemento raíz:

Comparación entre Pack URI absolutos y relativos

Un Pack URI completo incluye el esquema, la autoridad y la ruta de acceso, y se considera un Pack URI absoluto. Como simplificación para los desarrolladores, los elementos XAML habitualmente le permiten establecer los atributos adecuados con un Pack URI relativo, el que solo incluye la ruta de acceso.

Por ejemplo, considere el siguiente Pack URI absoluto para un archivo de recursos en el ensamblado local.

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

El Pack URI relativo que hace referencia a este archivos de recursos sería el siguiente.

/ResourceFile.xaml

Nota

Como los archivos de sitio de origen no están asociados con los ensamblados, solo se puede hacer referencia a ellos con Pack URI absolutos.

De manera predeterminada, un Pack URI relativo se considera relativo a la ubicación del marcado o del código que contiene la referencia. Sin embargo, si se usa una barra diagonal inversa, la referencia de Pack URI relativo se considera relativa a la raíz de la aplicación. Por ejemplo, considere la estructura de proyecto siguiente.

App.xaml

Page2.xaml

\SubFolder

+ Page1.xaml

+ Page2.xaml

Si Page1.xaml contiene un identificador URI que hace referencia a Raíz\Subcarpeta\Page2.xaml, la referencia puede usar el siguiente Pack URI relativo.

Page2.xaml

Si Page1.xaml contiene un identificador URI que hace referencia a Raíz\Page2.xaml, la referencia puede usar el siguiente Pack URI relativo.

/Page2.xaml

Resolución de Pack URI

El formato de Pack URI permite que los Pack URI para los distintos tipos de archivos tengan la misma apariencia. Por ejemplo, considere el siguiente Pack URI absoluto.

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

Este Pack URI absoluto podría hacer referencia a un archivo de recursos del ensamblado local o a un archivo de contenido. Lo mismo se aplica al siguiente URI relativo.

/ResourceOrContentFile.xaml

Para determinar el tipo de archivo al que hace referencia un Pack URI, WPF resuelve los identificadores URI para los archivos de recursos en ensamblados locales y los archivos de contenido mediante la siguiente heurística:

  1. Sondee los metadatos del ensamblado para un atributo AssemblyAssociatedContentFileAttribute que coincida con el Pack URI.

  2. Si se encuentra el atributo AssemblyAssociatedContentFileAttribute, la ruta de acceso del Pack URI hace referencia a un archivo de contenido.

  3. Si no se encuentra el atributo AssemblyAssociatedContentFileAttribute, sondee los archivos de recursos establecidos que están compilados en el ensamblado local.

  4. Si se encuentra un archivo de recursos que coincida con la ruta de acceso del Pack URI, la ruta de acceso del Pack URI hace referencia a un archivo de recursos.

  5. Si no se encuentra el recurso, el identificador Uri creado internamente no es válido.

La resolución de URI no se aplica a los identificadores URI que hacen referencia a los siguientes archivos:

  • Archivos de contenido en ensamblados a los que se hace referencia: WPF no admite estos tipos de archivo.

  • Archivos incrustados en ensamblados a los que se hace referencia: los identificadores URI que los identifican son únicos porque incluyen tanto el nombre del ensamblado al que se hace referencia como el sufijo ;component.

  • Archivos de sitio de origen: los identificadores URI que los identifican son únicos porque son los únicos archivos que se pueden identificar mediante los Pack URI que contienen la autoridad siteoforigin:///.

Una simplificación que permite la resolución de Pack URI es que el código sea independiente, hasta cierto punto, de las ubicaciones de los archivos de recursos y de contenido. Por ejemplo, si tiene un archivo de recursos en el ensamblado local que se hubiese reconfigurado como un archivo de contenido, el Pack URI del recurso sigue siendo el mismo, al igual que el código que usa el Pack URI.

Programación con Pack URI

Muchas clases de WPF implementan propiedades que se pueden establecer con Pack URI, como:

Estas propiedades se pueden establecer tanto desde el marcado como desde el código. En esta sección se muestran las construcciones básicas para ambos y, luego, se muestran ejemplos de escenarios comunes.

Uso de los Pack URI en el marcado

Un Pack URI se especifica en el marcado estableciendo el elemento de un atributo con el Pack URI. Por ejemplo:

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

En la tabla 1 se muestran los diversos Pack URI absolutos que se pueden especificar en el marcado.

Tabla 1: Pack URI absolutos en el marcado

Archivo Pack URI absoluto
Archivo de recursos: ensamblado local "pack://application:,,,/ResourceFile.xaml"
Archivo de recursos en subcarpeta: ensamblado local "pack://application:,,,/Subfolder/ResourceFile.xaml"
Archivo de recursos: ensamblado al que se hace referencia "pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml"
Archivo de recursos en subcarpeta del ensamblado al que se hace referencia "pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
Archivo de recursos en el ensamblado al que se hace referencia con versiones "pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml"
Archivo de contenido "pack://application:,,,/ContentFile.xaml"
Archivo de contenido en subcarpeta "pack://application:,,,/Subfolder/ContentFile.xaml"
Archivo de sitio de origen "pack://siteoforigin:,,,/SOOFile.xaml"
Archivo de sitio de origen en subcarpeta "pack://siteoforigin:,,,/Subfolder/SOOFile.xaml"

En la tabla 2 se muestran los diversos Pack URI relativos que se pueden especificar en el marcado.

Tabla 2: Pack URI relativos en el marcado

Archivo Pack URI relativo
Archivo de recursos en el ensamblado local "/ResourceFile.xaml"
Archivo de recursos en subcarpeta del ensamblado local "/Subfolder/ResourceFile.xaml"
Archivo de recursos en el ensamblado al que se hace referencia "/ReferencedAssembly;component/ResourceFile.xaml"
Archivo de recursos en subcarpeta del ensamblado al que se hace referencia "/ReferencedAssembly;component/Subfolder/ResourceFile.xaml"
Archivo de contenido "/ContentFile.xaml"
Archivo de contenido en subcarpeta "/Subfolder/ContentFile.xaml"

Uso de los Pack URI en el código

Para especificar un Pack URI en el código, puede crear una instancia de la clase Uri y pasar el Pack URI como parámetro al constructor. Esto se muestra en el ejemplo siguiente.

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

De manera predeterminada, la clase Uri considera que los Pack URI son absolutos. Por consiguiente, se produce una excepción cuando se crea una instancia de la clase Uri con un Pack URI relativo.

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

Afortunadamente, la sobrecarga Uri(String, UriKind) del constructor de clase Uri acepta un parámetro de tipo UriKind que le permitirá especificar si un Pack URI es absoluto o relativo.

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

Solo debe especificar Absolute o Relative cuando se tiene la seguridad de que el Pack URI proporcionado es uno u otro. Si no se conoce el tipo de Pack URI que se usa, como cuando un usuario escribe un Pack URI en tiempo de ejecución, use RelativeOrAbsolute.

// Relative or Absolute URI provided by user via a text box
TextBox userProvidedUriTextBox = new TextBox();
Uri uri = new Uri(userProvidedUriTextBox.Text, UriKind.RelativeOrAbsolute);

En la tabla 3 se muestran los diversos Pack URI relativos que se pueden especificar en el código mediante System.Uri.

Tabla 3: Pack URI absolutos en el código

Archivo Pack URI absoluto
Archivo de recursos: ensamblado local Uri uri = new Uri("pack://application:,,,/ResourceFile.xaml", UriKind.Absolute);
Archivo de recursos en subcarpeta: ensamblado local Uri uri = new Uri("pack://application:,,,/Subfolder/ResourceFile.xaml", UriKind.Absolute);
Archivo de recursos: ensamblado al que se hace referencia Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Absolute);
Archivo de recursos en subcarpeta del ensamblado al que se hace referencia Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Absolute);
Archivo de recursos en el ensamblado al que se hace referencia con versiones Uri uri = new Uri("pack://application:,,,/ReferencedAssembly;v1.0.0.0;component/ResourceFile.xaml", UriKind.Absolute);
Archivo de contenido Uri uri = new Uri("pack://application:,,,/ContentFile.xaml", UriKind.Absolute);
Archivo de contenido en subcarpeta Uri uri = new Uri("pack://application:,,,/Subfolder/ContentFile.xaml", UriKind.Absolute);
Archivo de sitio de origen Uri uri = new Uri("pack://siteoforigin:,,,/SOOFile.xaml", UriKind.Absolute);
Archivo de sitio de origen en subcarpeta Uri uri = new Uri("pack://siteoforigin:,,,/Subfolder/SOOFile.xaml", UriKind.Absolute);

En la tabla 4 se muestran los diversos Pack URI relativos que se pueden especificar en el código mediante System.Uri.

Tabla 4: Pack URI relativos en el código

Archivo Pack URI relativo
Archivo de recursos: ensamblado local Uri uri = new Uri("/ResourceFile.xaml", UriKind.Relative);
Archivo de recursos en subcarpeta: ensamblado local Uri uri = new Uri("/Subfolder/ResourceFile.xaml", UriKind.Relative);
Archivo de recursos: ensamblado al que se hace referencia Uri uri = new Uri("/ReferencedAssembly;component/ResourceFile.xaml", UriKind.Relative);
Archivo de recursos en subcarpeta: ensamblado al que se hace referencia Uri uri = new Uri("/ReferencedAssembly;component/Subfolder/ResourceFile.xaml", UriKind.Relative);
Archivo de contenido Uri uri = new Uri("/ContentFile.xaml", UriKind.Relative);
Archivo de contenido en subcarpeta Uri uri = new Uri("/Subfolder/ContentFile.xaml", UriKind.Relative);

Escenarios comunes de Pack URI

En las secciones anteriores se explicó como construir Pack URI para identificar archivos de recursos, de contenido y de sitio de origen. En WPF, estas construcciones se usan de diversas formas. En las secciones siguientes, se abordan varios usos comunes.

Especificación de la UI que se va a mostrar cuando una aplicación se inicia por primera vez

StartupUri especifica la primera interfaz de usuario que se va a mostrar al iniciarse una aplicación WPF. En el caso de las aplicaciones independientes, la interfaz de usuario puede ser una ventana, tal como se muestra en el ejemplo siguiente.

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

Las aplicaciones independientes y las aplicaciones de explorador XAML (XBAP) también pueden especificar una página como interfaz de usuario inicial, tal como se muestra en el ejemplo siguiente.

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

Si la aplicación es una aplicación independiente y se especifica una página con StartupUri, WPF abrirá NavigationWindow para hospedar la página. En el caso de las aplicaciones de explorador XAML, la página se muestra en el navegador del host.

En el ejemplo siguiente se muestra cómo navegar a una página.

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

Para más información sobre las diversas maneras de navegar en WPF, consulte Información general sobre navegación.

Especificación de un icono de ventana

En el ejemplo siguiente se muestra cómo usar un identificador URI para especificar el icono de una ventana.

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

Para obtener más información, vea Icon.

Carga de archivos de imagen, audio y vídeo

WPF permite que las aplicaciones usen una amplia variedad de tipos multimedia, que se pueden identificar y cargar todos con Pack URI, tal como se muestra en los ejemplos siguientes.

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

Para obtener más información sobre cómo trabajar con contenido multimedia, consulte Gráficos y multimedia.

Carga de un diccionario de recursos desde el sitio de origen

Los diccionarios de recursos (ResourceDictionary) se pueden usar para ofrecer compatibilidad con los temas de aplicación. Una forma de crear y administrar temas consiste en crear varios temas como diccionarios de recursos que están ubicados en el sitio de origen de una aplicación. Esto permite agregar temas y actualizarlos sin tener que volver a compilar e implementar una aplicación. Estos diccionarios de recursos se pueden identificar y cargar mediante Pack URI, tal como se muestra en el ejemplo siguiente.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml">
  <Application.Resources>
    <ResourceDictionary Source="pack://siteoforigin:,,,/PageTheme.xaml" />
  </Application.Resources>
</Application>

Para obtener información general sobre los temas en WPF, consulte Aplicar estilos y plantillas.

Consulte también