Arquitectura de extensibilidad de WPF Designer

Actualización: noviembre 2007

Windows Presentation Foundation (WPF) Designer for Visual Studio es un entorno de edición visual para controles compuestos de WPF, implementados por el tipo UserControl. WPF Designer se basa en un marco de trabajo con una arquitectura extensible, que puede ampliar para crear su propia experiencia de diseño personalizada.

Extendiendo el modelo de objetos de WPF Designer, puede personalizar en gran medida el aspecto y el comportamiento del contenido de WPF en tiempo de diseño. Por ejemplo, puede extender WPF Designer de las maneras siguientes:

  • Personalizar los glifos de movimiento y cambio de tamaño con gráficos mejorados.

  • Agregar un glifo a la superficie de diseño que incline el control seleccionado al mover el mouse.

  • Modificar el aspecto y el comportamiento de un control en tiempo de diseño en las distintas herramientas.

La arquitectura de WPF Designer admite toda la fuerza expresiva de WPF. Esto permite crear numerosas experiencia de diseño visual que antes no eran posibles.

Modelo de objetos de WPF Designer

El modelo de objetos de WPF Designer es modular, lo que significa que al extender el tiempo de diseño, únicamente se extienden los elementos necesarios para sus propias características. No tiene que escribir gran cantidad de código de compatibilidad para habilitar sus características de diseño personalizadas. 

El modelo de objetos está compuesto de cinco unidades funcionales, que se describen en la tabla siguiente.

Unidad funcional

Description

Modelo de edición

Interfaz de programación para los objetos del diseñador.

Proveedores de características

Punto de extensibilidad principal en el marco de trabajo del diseñador.

Contexto de edición

Almacén central para el estado de un diseñador.

Herramientas

Herramientas para procesar los datos proporcionados por el usuario.

Almacén de metadatos

Almacén que contiene el comportamiento de un control en tiempo de diseño, para separar físicamente la lógica del diseñador de la lógica de tiempo de ejecución.

En la ilustración siguiente se muestra el modelo de objetos de WPF Designer.

Modelo de objetos de alto nivel

Nota:

WPF Designer admite el marco de extensibilidad completo. Expression Blend sólo admite editores de propiedades, carga de metadatos y concesión de licencias. Blend no admite acciones de menú ni adornos. 

Modelo de edición

El entorno de diseño interactúa con los controles de tiempo de ejecución mediante una interfaz de programación denominada modelo de edición. El modelo de edición está compuesto de tres subunidades funcionales: un modelo, un contenedor público que abstrae el modelo y una vista que representa la interfaz de usuario (IU) del modelo.

El entorno de diseño utiliza el tipo ModelItem para comunicarse con el modelo subyacente. Todos los cambios se realizan en los contenedores ModelItem, que afectan al modelo subyacente. Esto permite que el modelo sea simple. Los contenedores ModelItem administran las características complejas del diseñador, tales como la compatibilidad de transacciones, la traza de acciones deshechas y las notificaciones de cambios.

La clase ModelService proporciona el punto de entrada para el modelo de edición y para las notificaciones de eventos globales.

La clase ViewService asigna las representaciones visuales a los elementos del modelo subyacente.

Ambos servicios son necesarios para que el diseñador funcione. La clase DesignerView, que es responsable de procesar los datos proporcionados por el usuario y enrutarlos a los comandos, necesita estos dos servicios para asignar con precisión los datos proporcionados por el usuario al modelo.

Proveedores de características

El comportamiento en tiempo de diseño de los tipos se extiende mediante las clases FeatureProvider o FeatureConnector<FeatureProviderType>. La clase FeatureConnector<FeatureProviderType> administra una lista de objetos FeatureProvider.

La clase FeatureProvider proporciona el punto de extensibilidad más básico. Un proveedor de características es una característica o complemento ligero que normalmente no exige mucho al entorno de diseño y que se crea y destruye en un contexto determinado. Los proveedores de características se utilizan para agregar nuevos bits de la interfaz de usuario a la superficie de diseño o para modificar algún comportamiento básico. Por ejemplo, un proveedor de características podría agregar más controladores de arrastre o proporcionar un nuevo tipo de comportamiento al arrastrar el mouse.

Para tener acceso al nivel más profundo de extensibilidad, derive de la clase FeatureConnector<FeatureProviderType>. Esta clase expone un proveedor de servicios a través del cual las clases de conector de características derivadas pueden controlar eventos, así como solicitar y publicar servicios. Por ejemplo, podría implementar un conector de características para proporcionar una serialización específica del objeto o de interfaz de usuario de selección.

En general, se implementan características para extender los conceptos existentes. Implemente un conector de características para proporcionar nuevos conceptos. Para obtener más información, vea Proveedores de características y conectores de características.

Contexto de edición

En un diseñador en ejecución se acumula una cantidad significativa de información de estado. Por ejemplo, el estado del diseñador puede incluir qué objetos están seleccionados o el comportamiento que se produce cuando se presiona el botón primario. El estado del diseñador se almacena en una ubicación central para poder encontrarlo cuando se necesita. La clase EditingContext representa este repositorio central de estados para el diseñador.

La clase EditingContext separa el estado en dos categorías: datos y comportamiento. Los datos se almacenan como una tabla de elementos de contexto y el comportamiento se almacena como una tabla de servicios. Ambas tablas se indizan mediante una clave basada en tipos y son enumerables.

La clase ContextItem contiene un único fragmento de estado en el diseñador. Los elementos de contexto son inmutables, pero puede haber elementos de contexto nuevos que reemplacen a los existentes para simular la mutabilidad.

Se tiene acceso a los servicios a través de una propiedad Services, que devuelve una instancia de ServiceManager, y se tiene acceso a los elementos de contexto a través de una propiedad Items, que devuelve una instancia de ContextItemManager.

Comandos, tareas y herramientas

La arquitectura de herramientas de WPF Designer está compuesta de comandos, tareas y herramientas. 

Un comando es un identificador único que representa un determinado comportamiento. Por ejemplo, “Cut” es un comando que significa que se debe cortar el texto seleccionado y agregarlo al Portapapeles. El código que implementa “Cut” varía según las distintas aplicaciones e incluso dentro de una misma aplicación. Por ejemplo, cortar texto en un documento de Word constituye una implementación diferente que cortarlo en el cuadro de texto de búsqueda del mismo documento. Independientemente de la implementación, el comando “Cut” permanece constante.

WPF Designer aumenta el sistema de comandos de WPF introduciendo un concepto de comando de herramienta. Un comando de herramienta implementa la interfaz ICommand y es como la clase RoutedCommand.

Una tarea tiene una colección de enlaces de comando que permite agregar los comandos enrutados. La clase DesignerView tiene código que utiliza la misma estrategia del enrutamiento que los comandos de herramienta para buscar y ejecutar comandos enrutados que se definen en tareas. La clase DesignerView habilita tareas que admiten comandos de WPF comunes, como Copy.

Una herramienta es una clase que procesa los datos proporcionados por el usuario. Todos los datos proporcionados por el usuario entran en el diseñador como uno o más eventos de entrada. Esos eventos de entrada se pasan a la herramienta actualmente activa, que los convierte en enlaces de entrada. Si se devuelve un enlace de entrada, se ejecuta el comando dentro del enlace.

Una herramienta puede representar el modo global del diseñador. Por ejemplo, si el usuario está seleccionando componentes en la superficie de diseño, ese modo de selección es posible porque la herramienta activa proporciona enlaces y comandos de entrada que administran la selección. Cuando el usuario crea una nueva instancia de un control, se activa una herramienta diferente que proporciona un conjunto diferente de comandos, que se enlazan a los mismos enlaces de entrada.

Almacén de metadatos

En el marco de trabajo de WPF Designer, los metadatos que definen el comportamiento de un control en tiempo de diseño se factorizan en un ensamblado independiente que se denomina almacén de metadatos. En .NET Framework 3.5, el almacén de metadatos se implementa en tablas de atributos basadas en código, con un archivo XML externo que hace referencia al código del diseñador y un perfil. Las distintas herramientas pueden proporcionar diversos almacenes de metadatos con implementaciones totalmente diferentes del diseñador. Esto desacopla el comportamiento en tiempo de ejecución y en tiempo de diseño, para que pueda revisar el diseñador de manera independiente con respecto al control. Para obtener más información, vea Almacén de metadatos.

Creación de instancias del diseñador

En los pasos siguientes se muestra cómo el entorno WPF Designer puede crear una instancia de un tipo de diseñador de ejemplo. Este ejemplo ficticio muestra cómo un diseñador hipotético seleccionaría un solo control de botón en la superficie de diseño.

  1. El usuario invoca una acción definida mediante una herramienta que solicita la creación de diseñador personalizada.

  2. El entorno de diseño enumera una lista basada en XML de asociaciones entre características y tipos.

  3. El entorno de diseño agrega metadatos personalizados a estos tipos utilizando la clase TypeDescriptor. Por ejemplo, GrabHandleProvider se podría asociar a todos los tipos UIElement, incluso los derivados.

  4. Un generador de edición crea un almacén de edición, un contexto y un administrador de características, y rellena el almacén de edición.

  5. WPF Designer enumera todos los objetos UIElement, que expone el almacén de edición y llama al método InitializeFeatures para cada uno de ellos.

    1. Supongamos que se declara un elemento Button en esta jerarquía.

    2. FeatureManager busca FeatureAttribute en el botón. FeatureManager detecta FeatureAttribute en el botón de tipo GrabHandleProvider.

    3. FeatureManager continúa buscando en el tipo GrabHandleProvider y detecta FeatureConnectorAttribute asociado a él. FeatureConnectorAttribute especifica el SelectionConnector.

    4. FeatureManager determina que este host no existe todavía. FeatureManager crea SelectionConnector y lo agrega a la lista de hosts de características activos.

    5. El objeto SelectionConnector comienza a supervisar la superficie de diseño por si se producen cambios de selección. El objeto SelectionConnector también obtiene una referencia a la capa de adornos.

  6. El usuario cambia la selección al botón y la herramienta en tiempo de diseño provoca un evento de cambio de selección.

  7. SelectionConnector recibe esta notificación y crea todas las instancias de FeatureProvider basadas en selección asociadas al objeto seleccionado, incluso la instancia GrabHandleProvider.

  8. El SelectionConnector consulta GrabHandleProvider para obtener una lista de adornos y los agrega a la capa de adornos. Aparecen controladores de arrastre alrededor del botón seleccionado.

Ensamblados de WPF Designer

WPF Designer está compuesto de varios ensamblados que pertenecen a tres categorías: públicos, privados y específicos de Visual Studio.

Los ensamblados públicos exponen clases que se pueden utilizar para agregar la lógica en tiempo de diseño a los controles.

Los ensamblados específicos de Visual Studio y privados definen el conjunto de características de WPF Designer y sus interacciones con Visual Studio. En la tabla siguiente se muestra cómo se implementan las características de WPF Designer.

Assembly

API pública

Description

Microsoft.VisualStudio.Xaml.dll

No

Lógica de integración de Visual Studio SDK

Microsoft.Windows.Design.Host.dll

API pública para hospedar el diseñador (específica de Visual Studio)

Microsoft.Windows.Design.Developer.dll

No

Implementación de WPF Designer. Sólo la API pública es una tabla de atributos.

Microsoft.Windows.Design.Core.dll

Proporciona el fundamento básico para cualquier diseñador mediante un servicio y un plano anterior de datos, y la manipulación de metadatos. Se trata del único ensamblado compatible con Expression Blend.

Microsoft.Windows.Design.Extensibility.dll

Proporciona el modelo de extensibilidad mediante atributos.

Microsoft.Windows.Design.Interaction.dll

Proporciona clases de datos proporcionados por el usuario y de visualización.

Microsoft.Windows.Design.Markup.dll

Proporciona XAML (Lenguaje de marcado de aplicaciones extensible) y mecanismos de modelos de documentos.

Nota:

Los ensamblados representan límites de funcionalidad, no límites de espacios de nombres. Con frecuencia encontrará espacios de nombres que abarquen más de un ensamblado.

WPF Designer y la arquitectura del Diseñador de Windows Forms

La arquitectura de WPF Designer es significativamente diferente de la arquitectura del Diseñador de Windows Forms, que se caracteriza por la interfaz IComponent y el espacio de nombres System.ComponentModel. Para obtener más información, vea Comparar el marco de trabajo del Diseñador de Windows Forms con el marco de trabajo de WPF Designer

Vea también

Conceptos

Proveedores de características y conectores de características

Otros recursos

Desarrollar controles de formularios Windows Forms en tiempo de diseño

Extensibilidad de WPF Designer