Compartir a través de


Ámbitos de nombres XAML de WPF

Los ámbitos de nombres XAML son un concepto que identifica los objetos definidos en XAML. Los nombres de un ámbito de nombres XAML se pueden utilizar para establecer relaciones entre los nombres de objetos definidos por XAML y sus equivalentes de instancia en un árbol de objetos. Normalmente, los ámbitos de nombres XAML en código administrado de WPF se crean al cargar los elementos raíz de la página XAML individual de una aplicación XAML. La interfaz INameScope define los ámbitos de nombres XAML como objetos de programación. También los implementa la clase práctica NameScope.

Este tema contiene las secciones siguientes.

  • Ámbitos de nombres en aplicaciones de XAML cargado
  • Ámbitos de nombres XAML en estilos y plantillas
  • Ámbitos de nombres XAML y API relacionadas con nombres
  • Temas relacionados

Ámbitos de nombres en aplicaciones de XAML cargado

En un contexto de programación o informático más amplio, los conceptos de programación suelen incluir el principio de un identificador o nombre único que se puede utilizar para tener acceso a un objeto. Para los sistemas que utilizan identificadores o nombres, el ámbito de nombres define los límites dentro de los cuales un proceso o técnica buscará si se solicita un objeto con ese nombre, o los límites donde se aplica la singularidad de identificación de nombres. Estos principios generales son verdaderos para los ámbitos de nombres XAML. En WPF, los ámbitos de nombres XAML se crean en el elemento raíz de una página XAML al cargarla. Cada nombre especificado dentro de la página XAML empezando en la raíz de la página se agrega a un ámbito de nombres XAML pertinente.

En XAML de WPF, los elementos que son elementos raíz comunes (como Page y Window) siempre controlan un ámbito de nombres XAML. Si un elemento, como FrameworkElement o FrameworkContentElement, es el elemento raíz de la página en el marcado, un procesador XAML agrega implícitamente una raíz de Page para que Page pueda proporcionar un ámbito de nombres XAML de trabajo.

NotaNota

Las acciones de compilación de WPF crean un ámbito de nombres XAML para una producción XAML incluso si no se definen atributos Name o x:Name en algún elemento del marcado XAML.

Si intenta utilizar dos veces el mismo nombre en un ámbito de nombres XAML, se inicia una excepción. Para el XAML de WPF que tiene código subyacente y forma parte de una aplicación compilada, la excepción la inician las acciones de compilación de WPF en tiempo de compilación, al crear la clase generada para la página durante la compilación inicial del marcado. Para el XAML que no se compila por marcado mediante ninguna acción de compilación, las excepciones relacionadas con los problemas del ámbito de nombres XAML se podrían iniciar cuando se cargue el XAML. Los diseñadores XAML también podrían prever los problemas del ámbito de nombres XAML en tiempo de diseño.

Agregar objetos a los árboles de objetos en tiempo de ejecución

El momento en que se analiza el XAML representa el momento en el tiempo en que se crea y define un ámbito de nombres XAML de WPF. Si agrega un objeto a un árbol de objetos en un punto en el tiempo posterior al análisis del XAML que generó ese árbol, un valor Name o x:Name en el nuevo objeto no actualiza automáticamente la información en un ámbito de nombres XAML. Para agregar un nombre de un objeto en un ámbito de nombres XAML de WPF después de cargar el XAML, debe llamar a la implementación adecuada de RegisterName en el objeto que define el ámbito de nombres XAML, que normalmente es la raíz de la página XAML. Si el nombre no está registrado, no se puede hacer referencia al objeto agregado por su nombre mediante métodos como FindName y no se puede utilizar ese nombre para destinos de animación.

El escenario más común para los programadores de aplicaciones consiste en utilizar RegisterName para registrar los nombres en el ámbito de nombres XAML en la raíz actual. RegisterName forma parte de un importante escenario para guiones gráficos destinados a objetos para animaciones. Para obtener más información, vea Información general sobre objetos Storyboard.

Si llama a RegisterName en un objeto distinto al objeto que define el ámbito de nombres XAML, el nombre aún se registrará en el ámbito de nombres XAML en el que se encuentra el objeto que realiza la llamada, como si se hubiera llamado a RegisterName en el ámbito de nombres XAML que define el objeto.

Ámbitos de nombres XAML en código

Puede crear y, a continuación, utilizar ámbitos de nombres XAML en código. Las API y los conceptos relacionados con la creación del ámbito de nombres XAML son los mismos incluso para el uso en código puro, porque el procesador XAML de WPF utiliza estas API y conceptos al procesar el propio XAML. Los conceptos y las API existen principalmente para permitir buscar los objetos por su nombre dentro de un árbol de objetos que se suele definir total o parcialmente en XAML.

Para las aplicaciones que se crean mediante programación y no a partir de XAML cargado, el objeto que define un ámbito de nombres XAML debe implementar INameScope, o ser una clase derivada de FrameworkElement o de FrameworkContentElement, para admitir la creación de un ámbito de nombres XAML en sus instancias.

Además, para cualquier elemento que no se cargue y procese mediante un procesador de XAML, el ámbito de nombres XAML del objeto no se crea ni inicializa de manera predeterminada. Debe crear de manera explícita un nuevo ámbito de nombres XAML para cualquier objeto en el que vaya a registrar nombres seguidamente. Para crear un ámbito de nombres XAML, se llama al método SetNameScope estático. Especifique el objeto que lo poseerá como el parámetro dependencyObject y una nueva llamada al constructor NameScope como el parámetro value.

Si el objeto proporcionado como parámetro dependencyObject para el método SetNameScope no es una implementación de INameScope, FrameworkElement o FrameworkContentElement, llamar a RegisterName en cualquier elemento secundario no surtirá ningún efecto. Si no crea explícitamente el nuevo ámbito de nombres XAML, al llamar a RegisterName se iniciará una excepción.

Para obtener un ejemplo del uso de las API de ámbito de nombres XAML en código, vea Cómo: Definir un ámbito de nombres.

Ámbitos de nombres XAML en estilos y plantillas

Los estilos y plantillas de WPF proporcionan la capacidad de reutilizar y aplicar de nuevo el contenido de una manera sencilla. Sin embargo, los estilos y las plantillas también pueden incluir elementos con nombres XAML definidos en el nivel de plantilla. Esta misma plantilla se puede utilizar varias veces en una página. Por esta razón, los estilos y las plantillas definen sus propios ámbitos de nombres XAML, independientemente de la ubicación en un árbol de objetos donde se aplique el estilo o la plantilla.

Considere el ejemplo siguiente:

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

Aquí, se aplica la misma plantilla a dos botones diferentes. Si las plantillas no tuvieran ámbitos de nombres XAML discretos, el nombre TheBorder utilizado en la plantilla provocaría un conflicto de nombres en el ámbito de nombres XAML. Cada instancia que se crea de la plantilla tiene su propio ámbito de nombres XAML, por lo que en este ejemplo el ámbito de nombres XAML de cada instancia de la plantilla contendrá exactamente un nombre.

Los estilos también definen su propio ámbito de nombres XAML, principalmente para permitir la asignación de nombres concretos a los distintos componentes del guión. Estos nombres habilitan comportamientos concretos destinados a elementos de ese nombre, aunque se vuelva a definir la plantilla como parte de la personalización de un control.

A causa de los ámbitos de nombres XAML independientes, buscar elementos con nombre en una plantilla resulta más complicado que hacerlo en un elemento con nombre sin plantilla de una página. En primer lugar, debe determinar cuál es la plantilla aplicada, obteniendo el valor de la propiedad Template del control donde se aplica la plantilla. A continuación, se llama a la versión de plantilla de FindName, y se pasa el control donde se aplicó la plantilla como segundo parámetro.

Si usted es el autor de un control y genera una convención donde un elemento con nombre determinado de una plantilla aplicada es el destino para un comportamiento definido por el propio control, puede utilizar el método GetTemplateChild del código de implementación del control. El método GetTemplateChild se protege, de tal forma que únicamente su autor tiene acceso a él.

Si trabaja desde dentro de una plantilla y necesita obtener el espacio de nombres XAML donde se aplica la plantilla, obtenga el valor de TemplatedParent y, a continuación, llame a FindName desde allí. Un ejemplo de trabajo dentro de la plantilla sería escribir la implementación del controlador de eventos donde el evento se provocará desde un elemento de una plantilla aplicada.

Ámbitos de nombres XAML y API relacionadas con nombres

FrameworkElement tiene los métodos FindName, RegisterName y UnregisterName. Si el objeto para el que se llama a estos métodos posee un ámbito de nombres XAML, los métodos llaman a los métodos del ámbito de nombres XAML pertinente. De lo contrario, se comprueba el elemento primario por si posee un ámbito de nombres XAML, y este proceso continúa de forma recursiva hasta que se encuentra un ámbito de nombres XAML (debido al comportamiento del procesador de XAML, es seguro que hay un ámbito de nombres XAML en la raíz). FrameworkContentElement tiene comportamientos análogos, con la excepción de que ningún FrameworkContentElement poseerá jamás un ámbito de nombres de XAML. Los métodos existen en FrameworkContentElement para que las llamadas se puedan reenviar, en caso necesario, a un elemento primario FrameworkElement.

SetNameScope se utiliza para asignar un nuevo ámbito de nombres XAML a un objeto existente. Puede llamar más de una vez a SetNameScope a fin de restablecer o borrar el ámbito de nombres XAML, pero no suele hacerse. GetNameScope tampoco se suele utilizar mediante código.

Implementaciones de ámbitos de nombres XAML

Las clases siguientes implementan INameScope directamente:

ResourceDictionary no utiliza nombres ni ámbitos de nombres XAML, sino claves, porque es una implementación de diccionario. La única razón por la que ResourceDictionary implementa INameScope es para poder iniciar excepciones en el código de usuario que ayuden a aclarar la distinción entre un ámbito de nombres XAML verdadero y la manera de administrar las claves por parte de ResourceDictionary, además de asegurarse de que ningún elemento primario aplique ámbitos de nombres XAML a ResourceDictionary.

FrameworkTemplate y Style implementan INameScope mediante definiciones de interfaz explícitas. Las implementaciones explícitas permiten que estos ámbitos de nombres XAML se comporten de un modo convencional cuando se tiene acceso a ellos a través de la interfaz INameScope, que es el modo que los procesos internos de WPF utilizan para comunicar los ámbitos de nombres XAML. No obstante, las definiciones de interfaz explícitas no forman parte de la superficie de API convencional de FrameworkTemplate y Style, porque casi nunca se necesita llamar directamente a los métodos INameScope en FrameworkTemplate y Style y, en su lugar, se utilizaría otra API, como GetTemplateChild.

Las clases siguientes definen su propio ámbito de nombres XAML, utilizando la clase de aplicación auxiliar System.Windows.NameScope y conectándose a su implementación de ámbito de nombres XAML a través de la propiedad adjunta NameScope.NameScope:

Vea también

Referencia

x:Name (Directiva)

Conceptos

Espacios de nombres y asignación de espacios de nombres XAML para WPF