Freigeben über


Erstellen einer Windows Forms-basierten domänenspezifischen Sprache

Sie können Windows Forms verwenden, um den Status eines DSL-Modells (Domain-Specific Language, domänenspezifische Sprache) anzuzeigen, anstatt ein DSL-Diagramm zu verwenden. Dieses Thema führt Sie durch das Binden eines Windows-Formulars an eine DSL mithilfe des Visualisierungs- und Modellierungs-SDK von Visual Studio.

Die folgende Abbildung zeigt die Benutzeroberfläche eines Windows-Formulars und den Modell-Explorer für eine DSL-Instanz:

DSL instance in Visual Studio

Erstellen einer Windows Forms-DSL

Mit der DSL-Vorlage Minimal WinForm Designer (Minimaler WinForms-Designer) wird eine minimale DSL erstellt, die Sie an Ihre eigenen Anforderungen anpassen können.

  1. Erstellen Sie eine DSL aus der Vorlage Minimal WinForm Designer.

    In dieser exemplarischen Vorgehensweise werden die folgenden Namen verwendet:

    • Projektmappen- und DSL-Name: FarmApp
    • Namespace: Company.FarmApp
  2. Experimentieren Sie mit dem anfänglichen Beispiel, das die Vorlage bereitstellt:

    1. Transformieren Sie alle Vorlagen.

    2. Erstellen Sie das Beispiel, und führen Sie es aus (STRG+F5).

    3. Öffnen Sie in der experimentellen Instanz von Visual Studio die Datei Sample im Debugprojekt.

      Beachten Sie, dass sie in einem Windows Forms-Steuerelement angezeigt wird.

      Sie können die Elemente des Modells auch im Explorer anzeigen.

      Fügen Sie einige Elemente entweder im Formular oder im Explorer hinzu, und beachten Sie, dass sie in der anderen Anzeige angezeigt werden.

    Beachten Sie in der Hauptinstanz von Visual Studio die folgenden Punkte zur DSL-Lösung:

  • DslDefinition.dsl enthält keine Diagrammelemente. Dies liegt daran, dass Sie keine DSL-Diagramme verwenden, um Instanzmodelle dieser DSL anzuzeigen. Stattdessen binden Sie ein Windows-Formular an das Modell, und die Elemente im Formular zeigen das Modell an.

  • Zusätzlich zu den Dsl- und DslPackage-Projekten enthält die Projektmappe ein drittes Projekt namens UI.UI, das die Definition eines Windows Forms-Steuerelements enthält. DslPackage hängt von UI und UI von Dsl ab.

  • UI\DocView.cs enthält im DslPackage-Projekt den Code, der das im UI-Projekt definierte Windows Forms-Steuerelement anzeigt.

  • Das UI-Projekt enthält ein funktionierendes Beispiel eines Formularsteuerelements, das an die DSL gebunden ist. Dies funktioniert jedoch nicht, wenn Sie die DSL-Definition geändert haben. Das UI-Projekt enthält Folgendes:

    • Eine Windows Forms-Klasse namens ModelViewControl.

    • Eine Datei mit dem Namen DataBinding.cs, die eine zusätzliche Teildefinition von ModelViewControl enthält. Um den Inhalt anzuzeigen, öffnen Sie im Projektmappen-Explorer das Kontextmenü für die Datei, und wählen Sie Code anzeigen aus.

Informationen zum UI-Projekt

Wenn Sie die DSL-Definitionsdatei aktualisieren, um Ihre eigene DSL zu definieren, müssen Sie das Steuerelement im UI-Projekt aktualisieren, um Ihre DSL anzuzeigen. Im Gegensatz zu den Dsl- und DslPackage-Projekten wird das UI-Beispielprojekt nicht aus DslDefinitionl.dsl generiert. Sie können TT-Dateien hinzufügen, um den Code auf Wunsch zu generieren. Dies wird in dieser exemplarischen Vorgehensweise jedoch nicht behandelt.

Aktualisieren der DSL-Definition

Die folgende Abbildung zeigt die DSL-Definition, die in dieser exemplarischen Vorgehensweise verwendet wird.

DSL definition

  1. Öffnen Sie „dslDefinition.dsl“ im DSL-Designer.

  2. Löschen Sie ExampleElement.

  3. Benennen Sie die ExampleModel-Domänenklasse in Farm um.

    Weisen Sie ihr zusätzliche Domäneneigenschaften mit dem Namen Size vom Typ Int32 und IsOrganic vom Typ Boolean zu.

    Hinweis

    Wenn Sie die Stammdomänenklasse löschen und dann einen neuen Stamm erstellen, müssen Sie die Eigenschaft „Editor Root Class“ (Stammklasse des Editors) zurücksetzen. Wählen Sie im DSL-Explorer die Option Editor aus. Legen Sie dann im Eigenschaftenfenster Stammklasse auf den Wert Farm fest.

  4. Verwenden Sie das Tool Named Domain Class (Benannte Domänenklasse), um die folgenden Domänenklassen zu erstellen:

    • Field: Weisen Sie eine zusätzliche Domäneneigenschaft mit dem Namen Size zu.

    • Animal: Legen Sie im Eigenschaftenfenster Inheritance Modifier (Vererbungsmodifizierer) auf Abstract fest.

    Hinweis

    Das Tool Named Domain Class und die anderen in diesem Abschnitt genannten Tools befinden sich im Toolfenster Toolbox. Sie können dieses Fenster mit Ansicht>Toolbox öffnen oder ausblenden.

  5. Verwenden Sie das Tool Domain Class (Domänenklasse), um die folgenden Klassen zu erstellen:

    • Sheep

    • Goat

  6. Verwenden Sie das Tool Inheritance (Vererbung), um zu erreichen, dass Goat und Sheep von Animal erben.

  7. Verwenden Sie das Tool Embedding (Einbettung), um Field und Animal unter Farm einzubetten.

  8. Möglicherweise möchten Sie das Diagramm bereinigen. Um die Anzahl doppelter Elemente zu reduzieren, verwenden Sie den Befehl Bring Subtree Here (Teilstruktur hierhin verschieben) im Kontextmenü von Blattelementen.

  9. Transformieren Sie alle Vorlagen auf der Symbolleiste des Projektmappen-Explorers.

  10. Erstellen Sie das Dsl-Projekt.

    Hinweis

    In dieser Phase werden die anderen Projekte nicht fehlerfrei erstellt. Wir möchten das Dsl-Projekt jedoch so erstellen, dass seine Assembly für den Datenquellen-Assistenten verfügbar ist.

Aktualisieren des UI-Projekts

Nun können Sie ein neues Benutzersteuerelement erstellen, das die im DSL-Modell gespeicherten Informationen anzeigt. Die einfachste Möglichkeit, das Benutzersteuerelement mit dem Modell zu verbinden, sind Datenbindungen. Der Datenbindungsadaptertyp mit dem Namen ModelingBindingSource wurde speziell für das Verbinden von DSLs mit Nicht-VMSDK-Schnittstellen entwickelt.

Definieren Ihres DSL-Modells als Datenquelle

  1. Klicken Sie im Menü Daten auf Datenquellen anzeigen.

    Das Fenster Datenquellen wird geöffnet.

    Wählen Sie Neue Datenquelle hinzufügen aus. Der Assistent zum Konfigurieren von Datenquellen wird geöffnet.

  2. Wählen Sie Objekt und dannWeiter aus.

    Erweitern Sie Dsl, Company.FarmApp, und wählen Sie Farm aus, die Stammklasse Ihres Modells. Klicken Sie auf Fertig stellen.

    Im Projektmappen-Explorer enthält das UI-Projekt jetzt Properties\DataSources\Farm.datasource.

    Die Eigenschaften und Beziehungen ihrer Modellklasse werden im Fenster „Datenquellen“ angezeigt.

    Data sources window

Verbinden Ihres Modells mit einem Formular

  1. Löschen Sie im UI-Projekt alle vorhandenen CS-Dateien.

  2. Fügen Sie dem UI-Projekt eine neue FarmControlBenutzersteuerungsdatei mit dem Namen hinzu.

  3. Wählen Sie im Fenster Datenquellen im Dropdownmenü unter Farm die Option Details aus.

    Behalten Sie die Standardeinstellungen für die anderen Eigenschaften bei.

  4. Öffnen Sie „FarmControl.cs“ in der Entwurfsansicht.

    Ziehen Sie „Farm“ aus dem Fenster Datenquellen auf „FarmControl“.

    Es wird ein Satz von Steuerelementen angezeigt, eines für jede Eigenschaft. Die Beziehungseigenschaften generieren keine Steuerelemente.

  5. Löschen Sie farmBindingNavigator. Dies wird auch automatisch im FarmControl-Designer generiert, ist aber für diese Anwendung nicht hilfreich.

  6. Erstellen Sie mithilfe der Toolbox zwei Instanzen von DataGridView, und nennen Sie diese AnimalGridView und FieldGridView.

    Hinweis

    Ein alternativer Schritt besteht darin, die Elemente „Animals“ und „Fields“ aus dem Fenster „Datenquellen“ auf das Steuerelement zu ziehen. Diese Aktion erstellt automatisch Datenraster und Bindungen zwischen der Rasteransicht und der Datenquelle. Diese Bindung funktioniert für DSLs jedoch nicht ordnungsgemäß. Daher ist es besser, die Datenraster und Bindungen manuell zu erstellen.

  7. Wenn die Toolbox das Tool ModelingBindingSource nicht enthält, fügen Sie es hinzu. Wählen Sie im Kontextmenü der Registerkarte Daten die Option Elemente auswählen aus. Wählen Sie im Dialogfeld Toolboxelemente auswählen die Option ModelingBindingSource auf der Registerkarte .NET Framework aus.

  8. Erstellen Sie mit der Toolbox zwei Instanzen von ModelingBindingSource, und nennen Sie diese AnimalBinding und FieldBinding.

  9. Legen Sie die DataSource-Eigenschaft jeder ModelingBindingSource auf farmBindingSource fest.

    Legen Sie die DataMember-Eigenschaft auf Animals oder Fields fest.

  10. Legen Sie die DataSource-Eigenschaften von AnimalGridView auf AnimalBindingund von FieldGridView auf FieldBinding fest.

  11. Passen Sie das Layout des Farm-Steuerelements an Ihre Vorstellungen an.

    ModelingBindingSource ist ein Adapter, der mehrere DSLs-spezifische Funktionen ausführt:

  • Er umschließt Updates in einer VMSDK-Speichertransaktion.

    Wenn der Benutzer beispielsweise eine Zeile aus dem Datenansichtsraster löscht, würde eine reguläre Bindung zu einer Transaktionsausnahme führen.

  • Dadurch wird sichergestellt, dass das Eigenschaftenfenster die Eigenschaften des entsprechenden Modellelements anstelle der Datenrasterzeile anzeigt, wenn der Benutzer eine Zeile auswählt.

    Schema of the DSL binding

    Schema der Verknüpfungen zwischen Datenquellen und Ansichten.

Abschließen der Bindungen an die DSL

  1. Fügen Sie den folgenden Code in einer separaten Codedatei im UI-Projekt hinzu:

    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. Bearbeiten Sie im DslPackage-Projekt DslPackage\DocView.tt, um die folgende Variablendefinition zu aktualisieren:

    string viewControlTypeName = "FarmControl";
    

Testen der DSL

Die DSL-Lösung kann jetzt erstellt und ausgeführt werden, auch wenn Sie später möglicherweise weitere Verbesserungen hinzufügen möchten.

  1. Erstellen Sie das Projekt, und führen Sie es aus.

  2. Öffnen Sie in der experimentellen Instanz von Visual Studio die Datei Sample.

  3. Öffnen Sie im FarmApp-Explorer das Kontextmenü im Stammknoten Farm, und wählen Sie Add New Goat (Neue Ziege hinzufügen) aus.

    Goat1 wird in der Ansicht Animals (Tiere) angezeigt.

    Warnung

    Sie müssen das Kontextmenü im Knoten Farm verwenden, nicht den Knoten Animals (Tiere).

  4. Wählen Sie den Stammknoten Farm aus, und zeigen Sie dessen Eigenschaften an.

    Ändern Sie in der Formularansicht den Namen oder die Größe der Farm.

    Wenn Sie weg von jedem Feld im Formular navigieren, ändert sich die entsprechende Eigenschaft im Eigenschaftenfenster.

Optimieren der DSL

Sofortiges Aktualisieren der Eigenschaften

  1. Wählen Sie in der Entwurfsansicht von „FarmControl.cs“ ein einfaches Feld aus, z. B. „Name“, „Size“ (Größe) oder „IsOrganic“.

  2. Erweitern Sie im Eigenschaftenfenster DataBindings, und öffnen Sie (Advanced) (Erweitert).

    Wählen Sie im Dialogfeld Formatierung und erweiterte Bindung unter Datenquellen-Updatemodus die Option OnPropertyChanged aus.

  3. Erstellen Sie das Projekt, und führen Sie es aus.

    Stellen Sie sicher, dass sich die entsprechende Eigenschaft des Farm-Modells sofort ändert, wenn Sie den Inhalt des Felds ändern.

Bereitstellen von Schaltflächen „Hinzufügen“

  1. Verwenden Sie in der Entwurfsansicht von „FarmControl.cs“ die Toolbox, um eine Schaltfläche im Formular zu erstellen.

    Ändern Sie den Namen und den Text der Schaltfläche, z. B. in New Sheep.

  2. Öffnen Sie den Code hinter der Schaltfläche (z. B., indem Sie darauf doppelklicken).

    Bearbeiten Sie ihn wie folgt:

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

    Sie müssen auch die folgende Anweisung einfügen:

    
    using Microsoft.VisualStudio.Modeling;
    
  3. Fügen Sie ähnliche Schaltflächen für „Goats“ (Ziegen) und „Fields“ (Felder) hinzu.

  4. Erstellen Sie das Projekt, und führen Sie es aus.

  5. Vergewissern Sie sich, dass die neue Schaltfläche ein Element hinzufügt. Das neue Element sollte sowohl im FarmApp-Explorer als auch in der entsprechenden Datenrasteransicht angezeigt werden.

    Sie sollten in der Lage sein, den Namen des Elements in der Datenrasteransicht zu bearbeiten. Sie können es dort auch löschen.

    Sample data grid view

Informationen zum Code zum Hinzufügen eines Elements

Für die neuen Elementschaltflächen ist der folgende alternative Code etwas einfacher.

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();
  }
}

Dieser Code legt jedoch keinen Standardnamen für das neue Element fest. Es werden keine benutzerdefinierten Merges ausgeführt, die Sie möglicherweise in den Elementmerge-Anweisung der DSL definiert haben, und es wird kein benutzerdefinierter Mergecode ausgeführt, der möglicherweise definiert wurde.

Daher wird empfohlen, ElementOperations zu verwenden, um neue Elemente zu erstellen. Weitere Informationen finden Sie unter Anpassen der Elementerstellung und -verschiebung.