Creación de un lenguaje específico de dominio basado en Windows Forms
Puede usar Windows Forms para mostrar el estado de un modelo de lenguaje específico de dominio (DSL), en lugar de usar un diagrama de DSL. Este tema le guía por el proceso de enlazar un formulario de Windows Forms a un DSL mediante el SDK de visualización y modelado de Visual Studio.
En la imagen siguiente se muestra una interfaz de usuario de Windows Forms y el explorador de modelos para una instancia de DSL:
Creación de un DSL de Windows Forms
La plantilla de DSL Minimal WinForm Designer (Diseñador de WinForm mínimo) crea un DSL mínimo que puede modificar para adaptarlo a sus requisitos.
Cree un DSL a partir de la plantilla Minimal WinForm Designer (Diseñador de WinForm mínimo).
En este tutorial se da por supuesto que se usan los nombres siguientes:
- Nombre de solución y DSL:
FarmApp
- Espacio de nombres:
Company.FarmApp
- Nombre de solución y DSL:
Experimente con el ejemplo inicial que proporciona la plantilla:
Transforme todas las plantillas.
Compile y ejecute el ejemplo (CTRL+F5).
En la instancia experimental de Visual Studio, abra el archivo
Sample
en el proyecto de depuración.Observe que se muestra en un control de Windows Forms.
También puede ver los elementos del modelo en el Explorador.
Agregue algunos elementos en el formulario o en el Explorador y observe que aparecen en la otra pantalla.
En la instancia principal de Visual Studio, observe lo siguiente sobre la solución de DSL:
DslDefinition.dsl
no contiene elementos de diagrama. Esto se debe a que no se usarán diagramas de DSL para ver los modelos de instancia de este DSL. En su lugar, se enlazará un formulario de Windows Forms al modelo y los elementos del formulario mostrarán el modelo.Además de los proyectos
Dsl
yDslPackage
, la solución contiene un tercer proyecto denominadoUI.
El proyecto UI contiene la definición de un control de Windows Forms.DslPackage
depende deUI
, yUI
depende deDsl
.En el proyecto
DslPackage
,UI\DocView.cs
contiene el código que muestra el control de Windows Forms que se define en el proyectoUI
.El proyecto
UI
contiene un ejemplo práctico de un control de formulario enlazado al DSL, pero no funcionará si se ha cambiado la definición de DSL. El proyectoUI
contiene:Una clase de Windows Forms denominada
ModelViewControl
.Un archivo denominado
DataBinding.cs
que contiene una definición parcial adicional deModelViewControl
. Para ver su contenido, en el Explorador de soluciones, abra el menú contextual del archivo y seleccione Ver código.
Acerca del proyecto UI
Al actualizar el archivo de definición de DSL para definir su propio DSL, tendrá que actualizar el control en el proyecto UI
para mostrar su DSL. A diferencia de los proyectos Dsl
y DslPackage
, el proyecto UI
de ejemplo no se genera a partir de DslDefinitionl.dsl
. Puede agregar archivos .tt para generar el código si quiere, aunque esto no se trata en el presente tutorial.
Actualización de la definición de DSL
La siguiente imagen es la definición de DSL que se usa en este tutorial.
Abra DslDefinition.dsl en el diseñador de DSL.
Elimine ExampleElement.
Cambie el nombre de la clase de dominio ExampleModel a
Farm
.Asígnele propiedades de dominio adicionales, denominadas
Size
(de tipo Int32) eIsOrganic
(de tipo booleano).Nota
Si elimina la clase de dominio raíz y crea una raíz nueva, tendrá que restablecer la propiedad Clase raíz del Editor. En el Explorador de DSL, seleccione Editor. Después, en la ventana Propiedades, establezca Clase raíz en
Farm
.Use la herramienta Clase de dominio con nombre para crear las siguientes clases de dominio:
Field
: asígnele una propiedad de dominio adicional denominadaSize
.Animal
: en la ventana Propiedades, establezca Modificador de herencia en Abstracto.
Nota
La herramienta Clase de dominio con nombre y las demás herramientas que se mencionan en esta sección se encuentran en la ventana de herramientas del Cuadro de herramientas. Puede abrir u ocultar esta ventana con elVer>Cuadro de herramientas.
Use la herramienta Clase de dominio para crear las clases siguientes:
Sheep
Goat
Use la herramienta Herencia para hacer que
Goat
ySheep
hereden deAnimal
.Use la herramienta Inclusión para insertar
Field
yAnimal
enFarm
.Es posible que le interese ordenar el diagrama. Para reducir el número de elementos duplicados, use el comando Bring Subtree Here (Traer subárbol aquí) en el menú contextual de elementos hoja.
Transforme todas las plantillas en la barra de herramientas del Explorador de soluciones.
Compile el proyecto Dsl.
Nota
En esta fase, los otros proyectos no se compilarán sin errores. Aun así, queremos compilar el proyecto Dsl para que su ensamblado esté a disposición del Asistente para orígenes de datos.
Actualización del proyecto UI
Ahora puede crear un control de usuario que muestre la información que está almacenada en el modelo de DSL. La manera más fácil de conectar el control de usuario al modelo es mediante enlaces de datos. El tipo de adaptador de enlace de datos denominado ModelingBindingSource está diseñado específicamente para conectar los DSL a interfaces que no son VMSDK.
Definición del modelo de DSL como origen de datos
En el menú Datos, seleccione Mostrar orígenes de datos.
Se abre la ventana Orígenes de datos.
Seleccione Agregar nuevo origen de datos. Se abrirá el Asistente para configuración de orígenes de datos.
Seleccione Objeto y Siguiente.
Expanda Dsl, Company.FarmApp y seleccione Farm, que es la clase raíz del modelo. Elija Finalizar.
En el Explorador de soluciones, el proyecto UI ahora contiene Properties\DataSources\Farm.datasource.
Las propiedades y relaciones de la clase de modelo aparecen en la ventana Orígenes de datos.
Conexión del modelo a un formulario
En el proyecto UI, elimine todos los archivos .cs existentes.
Agregue un nuevo archivo Control de usuario denominado
FarmControl
al proyecto UI.En la ventana Orígenes de datos, en el menú desplegable de Farm, elija Detalles.
Deje la configuración predeterminada para las demás propiedades.
Abra FarmControl.cs en la vista de diseño.
Arrastre Farm desde la ventana Orígenes de datos a FarmControl.
Aparece un conjunto de controles, uno para cada propiedad. Las propiedades de relación no generan controles.
Elimine farmBindingNavigator. Esto también se genera automáticamente en el diseñador
FarmControl
, pero no es útil para esta aplicación.Con el cuadro de herramientas, cree dos instancias de DataGridView y asígneles el nombre
AnimalGridView
yFieldGridView
.Nota
Un paso alternativo consiste en arrastrar los elementos Animals y Fields desde la ventana Orígenes de datos al control. Esta acción crea automáticamente cuadrículas de datos y enlaces entre la vista de cuadrícula y el origen de datos. Aun así, este enlace no funciona correctamente para los DSL. Por lo tanto, es mejor crear manualmente las cuadrículas de datos y los enlaces.
Si el cuadro de herramientas no contiene la herramienta ModelingBindingSource, agréguela. En el menú contextual de la pestaña Datos, seleccione Elegir elementos. En el cuadro de diálogo Elegir elementos del cuadro de herramientas, seleccione ModelingBindingSource en la pestaña .NET Framework.
Con el cuadro de herramientas, cree dos instancias de ModelingBindingSource y asígneles el nombre
AnimalBinding
yFieldBinding
.Establezca la propiedad DataSource de cada ModelingBindingSource en farmBindingSource.
Establezca la propiedad DataMember en Animals o Fields.
Establezca las propiedades DataSource de
AnimalGridView
enAnimalBinding
, y deFieldGridView
enFieldBinding
.Ajuste el diseño del control Farm a su gusto.
ModelingBindingSource es un adaptador que realiza varias funciones específicas de los DSL:
Encapsula las actualizaciones en una transacción de almacén de VMSDK.
Por ejemplo, cuando el usuario elimina una fila de la cuadrícula de la vista de datos, un enlace normal provocaría una excepción de transacción.
Garantiza que, cuando el usuario selecciona una fila, la ventana Propiedades muestra las propiedades del elemento de modelo correspondiente, en lugar de la fila de cuadrícula de datos.
Esquema de los vínculos entre los orígenes de datos y las vistas.
Finalización de los enlaces al DSL
Agregue el código siguiente en un archivo de código independiente en el proyecto UI:
using System.ComponentModel; using Microsoft.VisualStudio.Modeling; using Microsoft.VisualStudio.Modeling.Design; namespace Company.FarmApp { partial class FarmControl { public IContainer Components { get { return components; } } /// <summary>Binds the WinForms data source to the DSL model. /// </summary> /// <param name="nodelRoot">The root element of the model.</param> public void DataBind(ModelElement modelRoot) { WinFormsDataBindingHelper.PreInitializeDataSources(this); this.farmBindingSource.DataSource = modelRoot; WinFormsDataBindingHelper.InitializeDataSources(this); } } }
En el proyecto DslPackage, edite DslPackage\DocView.tt para actualizar la siguiente definición de variable:
string viewControlTypeName = "FarmControl";
Prueba del DSL
La solución de DSL ahora puede compilarse y ejecutarse, aunque es posible que le interese agregar otras mejoras más adelante.
Compile y ejecute la solución.
En la instancia experimental de Visual Studio, abra el archivo Sample.
En el Explorador de FarmApp, abra el menú contextual del nodo raíz Farm y elija Agregar nuevo Goat.
Goat1
aparece en la vista Animals.Advertencia
Debe usar el menú contextual del nodo Farm, no del nodo Animals.
Seleccione el nodo raíz Farm y visualice sus propiedades.
En la vista de formulario, cambie el nombre o el tamaño de Farm.
Cuando salga de cada campo del formulario, la propiedad correspondiente cambiará en la ventana Propiedades.
Mejora del DSL
Actualización inmediata las propiedades
En la vista de diseño de FarmControl.cs, seleccione un campo simple, como Name, Size o IsOrganic.
En la ventana Propiedades, expanda DataBindings y abra (Avanzado).
En el cuadro de diálogo Formato y enlace de datos avanzado, en Modo de actualización del origen de datos, elija OnPropertyChanged.
Compile y ejecute la solución.
Compruebe que, al cambiar el contenido del campo, la propiedad correspondiente del modelo Farm cambia inmediatamente.
Inclusión de botones Agregar
En la vista de diseño de FarmControl.cs, use el cuadro de herramientas para crear un botón en el formulario.
Edite el nombre y el texto del botón. Por ejemplo, cámbielo a
New Sheep
.Abra el código subyacente al botón (por ejemplo, haga doble clic en él).
Edítelo de la manera siguiente:
private void NewSheepButton_Click(object sender, EventArgs e) { using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep")) { elementOperations.MergeElementGroup(farm, new ElementGroup(new Sheep(farm.Partition))); t.Commit(); } } // The following code is shared with other add buttons: private ElementOperations operationsCache = null; private ElementOperations elementOperations { get { if (operationsCache == null) { operationsCache = new ElementOperations(farm.Store, farm.Partition); } return operationsCache; } } private Farm farm { get { return this.farmBindingSource.DataSource as Farm; } }
También tendrá que insertar la directiva siguiente:
using Microsoft.VisualStudio.Modeling;
Agregue botones similares para Goats y Fields.
Compile y ejecute la solución.
Compruebe que el nuevo botón agrega un elemento. El nuevo elemento debe aparecer en el Explorador de FarmApp y en la vista de cuadrícula de datos correspondiente.
Debería poder editar el nombre del elemento en la vista de cuadrícula de datos. También puede eliminarlo desde allí.
Acerca del código para agregar un elemento
Para los botones de elementos nuevos, el siguiente código alternativo es algo más sencillo.
private void NewSheepButton_Click(object sender, EventArgs e)
{
using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep"))
{
farm.Animals.Add(new Sheep(farm.Partition)); ;
t.Commit();
}
}
Aun así, este código no establece un nombre predeterminado para el nuevo elemento. No ejecuta ninguna combinación personalizada que haya definido en las directivas de fusión de elementos mediante combinación del DSL y tampoco ejecuta ningún código de combinación personalizado que se haya definido.
Por lo tanto, se recomienda usar ElementOperations para crear elementos. Para obtener más información, consulte Personalización de la creación y el movimiento de los elementos.