Compartir a través de


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:

DSL instance in Visual Studio

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.

  1. 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
  2. Experimente con el ejemplo inicial que proporciona la plantilla:

    1. Transforme todas las plantillas.

    2. Compile y ejecute el ejemplo (CTRL+F5).

    3. 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 y DslPackage, la solución contiene un tercer proyecto denominado UI. El proyecto UI contiene la definición de un control de Windows Forms. DslPackage depende de UI, y UI depende de Dsl.

  • En el proyecto DslPackage, UI\DocView.cs contiene el código que muestra el control de Windows Forms que se define en el proyecto UI.

  • 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 proyecto UI contiene:

    • Una clase de Windows Forms denominada ModelViewControl.

    • Un archivo denominado DataBinding.cs que contiene una definición parcial adicional de ModelViewControl. 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.

DSL definition

  1. Abra DslDefinition.dsl en el diseñador de DSL.

  2. Elimine ExampleElement.

  3. Cambie el nombre de la clase de dominio ExampleModel a Farm.

    Asígnele propiedades de dominio adicionales, denominadas Size (de tipo Int32) e IsOrganic (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.

  4. Use la herramienta Clase de dominio con nombre para crear las siguientes clases de dominio:

    • Field: asígnele una propiedad de dominio adicional denominada Size.

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

  5. Use la herramienta Clase de dominio para crear las clases siguientes:

    • Sheep

    • Goat

  6. Use la herramienta Herencia para hacer que Goat y Sheep hereden de Animal.

  7. Use la herramienta Inclusión para insertar Field y Animal en Farm.

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

  9. Transforme todas las plantillas en la barra de herramientas del Explorador de soluciones.

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

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

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

    Data sources window

Conexión del modelo a un formulario

  1. En el proyecto UI, elimine todos los archivos .cs existentes.

  2. Agregue un nuevo archivo Control de usuario denominado FarmControl al proyecto UI.

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

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

  5. Elimine farmBindingNavigator. Esto también se genera automáticamente en el diseñador FarmControl, pero no es útil para esta aplicación.

  6. Con el cuadro de herramientas, cree dos instancias de DataGridView y asígneles el nombre AnimalGridView y FieldGridView.

    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.

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

  8. Con el cuadro de herramientas, cree dos instancias de ModelingBindingSource y asígneles el nombre AnimalBinding y FieldBinding.

  9. Establezca la propiedad DataSource de cada ModelingBindingSource en farmBindingSource.

    Establezca la propiedad DataMember en Animals o Fields.

  10. Establezca las propiedades DataSource de AnimalGridView en AnimalBinding, y de FieldGridView en FieldBinding.

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

    Schema of the DSL binding

    Esquema de los vínculos entre los orígenes de datos y las vistas.

Finalización de los enlaces al DSL

  1. 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);
        }
      }
    }
    
  2. 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.

  1. Compile y ejecute la solución.

  2. En la instancia experimental de Visual Studio, abra el archivo Sample.

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

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

  1. En la vista de diseño de FarmControl.cs, seleccione un campo simple, como Name, Size o IsOrganic.

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

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

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

  2. 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;
    
  3. Agregue botones similares para Goats y Fields.

  4. Compile y ejecute la solución.

  5. 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í.

    Sample data grid view

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.