Aktualisieren von Formen und Connectors zur Darstellung des Modells

In einer domänenspezifischen Sprache in Visual Studio können Sie dafür sorgen, dass das Erscheinungsbild einer Form den Zustand des zugrunde liegenden Modells widerspiegelt.

Die Codebeispiele in diesem Thema müssen der .cs-Datei im Dsl-Projekt hinzugefügt werden. Sie benötigen diese Anweisungen in jeder Datei:

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

Festlegen von Formzuordnungseigenschaften zum Steuern der Sichtbarkeit eines Decorators

Sie können die Sichtbarkeit eines Decorators steuern, ohne Programmcode schreiben zu müssen, indem Sie die Zuordnung zwischen der Form und der Domänenklasse in der DSL-Definition konfigurieren. Weitere Informationen finden Sie unter Definieren einer domänenspezifischen Sprache.

Verfügbarmachen der Farbe und des Stils einer Form als Eigenschaften

Klicken Sie in der DSL-Definition mit der rechten Maustaste auf die Formklasse, zeigen Sie auf Bereitgestellte hinzufügen, und klicken Sie auf eines der Elemente, z. B. auf Füllfarbe.

Die Form verfügt nun über eine Domäneneigenschaft, die Sie im Programmcode oder als Benutzer*in festlegen können. Wenn Sie diese beispielsweise im Programmcode eines Befehls oder einer Regel festlegen möchten, können Sie Folgendes schreiben:

shape.FillColor = System.Drawing.Color.Red;

Wenn Sie möchten, dass die Eigenschaftsvariable nur mittels Programm und nicht durch Benutzer*innen festgelegt wird, wählen Sie im Diagramm „DSL-Definition“ die neue Domäneneigenschaft aus, z. B. Füllfarbe. Legen Sie dann im Eigenschaftenfenster Is Browsable auf false fest, oder legen Sie Is UI Readonly auf true fest.

Definieren von Änderungsregeln zum Festlegen, dass Farben, Stile oder Speicherorte von Modellelementeigenschaften abhängen

Sie können Regeln definieren, die die Darstellung der Form aktualisieren, die von anderen Teilen des Modells abhängig ist. Sie können z. B. eine Änderungsregel für ein Modellelement definieren, das die Farbe der Form aktualisiert, die von den Eigenschaften des Modellelements abhängig ist. Weitere Informationen zu Änderungsregeln finden Sie unter Regeln propagieren Änderungen im Modell.

Sie sollten Regeln nur verwenden, um Eigenschaften zu aktualisieren, die im Speicher verwaltet werden, da Regeln nicht aufgerufen werden, wenn der Befehl „Rückgängig“ ausgeführt wird. Einige grafische Features wie Größe und Sichtbarkeit einer Form gehören nicht dazu. Informationen zum Aktualisieren dieser Features einer Form finden Sie unter Aktualisieren von grafischen Features außerhalb des Speichers.

Im folgenden Beispiel wird davon ausgegangen, dass Sie FillColor als Domäneneigenschaft verfügbar gemacht haben, wie im vorherigen Abschnitt beschrieben.

[RuleOn(typeof(ExampleElement))]
  class ExampleElementPropertyRule : ChangeRule
  {
    public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
    {
      base.ElementPropertyChanged(e);
      ExampleElement element = e.ModelElement as ExampleElement;
      // The rule is called for every property that is updated.
      // Therefore, verify which property changed:
      if (e.DomainProperty.Id == ExampleElement.NameDomainPropertyId)
      {
        // There is usually only one shape:
        foreach (PresentationElement pel in PresentationViewsSubject.GetPresentation(element))
        {
          ExampleShape shape = pel as ExampleShape;
          // Replace this with a useful condition:
          shape.FillColor = element.Name.EndsWith("3")
                     ? System.Drawing.Color.Red : System.Drawing.Color.Green;
        }
      }
    }
  }
  // The rule must be registered:
  public partial class OnAssociatedPropertyExptDomainModel
  {
    protected override Type[] GetCustomDomainModelTypes()
    {
      List<Type> types = new List<Type>(base.GetCustomDomainModelTypes());
      types.Add(typeof(ExampleElementPropertyRule));
      // If you add more rules, list them here.
      return types.ToArray();
    }
  }

Verwenden von OnChildConfigured zum Initialisieren der Eigenschaften einer Form

Wenn die Eigenschaften einer Form beim ersten Erstellen festgelegt werden sollen, überschreiben Sie OnChildConfigured() in einer partiellen Definition der Diagrammklasse. Die Diagrammklasse wird in einer DSL-Definition angegeben, und der generierte Code befindet sich in Dsl\Generated Code\Diagram.cs. Beispiel:

partial class MyLanguageDiagram
{
  protected override void OnChildConfigured(ShapeElement child, bool childWasPlaced, bool createdDuringViewFixup)
  {
    base.OnChildConfigured(child, childWasPlaced, createdDuringViewFixup);
    ExampleShape shape = child as ExampleShape;
    if (shape != null)
    {
      if (!createdDuringViewFixup) return; // Ignore load from file.
      ExampleElement element = shape.ModelElement as ExampleElement;
      // Replace with a useful condition:
      shape.FillColor = element.Name.EndsWith("3")
          ? System.Drawing.Color.Red : System.Drawing.Color.Green;
    }
    // else deal with other types of shapes and connectors.
  }
}

Diese Methode kann sowohl für Domäneneigenschaften als auch für Features außerhalb des Speichers verwendet werden, z. B. für die Größe der Form.

Verwenden von AssociateValueWith() zum Aktualisieren anderer Features einer Form

Bei einigen Features einer Form, z. B. ob sie über einen Schatten verfügt oder welche Pfeilart ein Connector aufweist, gibt es keine integrierte Methode zum Verfügbarmachen des Features als Domäneneigenschaft. Änderungen an diesen Features unterliegen nicht der Kontrolle des Transaktionssystems. Daher kann es nicht zum Aktualisieren von Regeln verwendet werden, da Regeln nicht aufgerufen werden, wenn Benutzer*innen den Befehl „Rückgängig“ ausführen.

Stattdessen können Sie diese Features mithilfe von OnAssociatedPropertyChanged aktualisieren. Im folgenden Beispiel wird die Pfeilart eines Connectors durch den Wert einer Domäneneigenschaft in der Beziehung bestimmt, die vom Connector angezeigt wird:

public partial class ArrowConnector // My connector class.
{
    /// <summary>
    /// Called whenever a registered property changes in the associated model element.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnAssociatedPropertyChanged(VisualStudio.Modeling.Diagrams.PropertyChangedEventArgs e)
    {
      base.OnAssociatedPropertyChanged(e);
      // Can be called for any property change. Therefore,
      // Verify that this is the property we're interested in:
      if ("IsDirected".Equals(e.PropertyName))
      {
        if (e.NewValue.Equals(true))
        { // Update the shape's built-in Decorator feature:
          this.DecoratorTo = LinkDecorator.DecoratorEmptyArrow;
        }
        else
        {
          this.DecoratorTo = null; // No arrowhead.
        }
      }
    }

    // OnAssociatedPropertyChanged is called only for properties
    // that have been registered using AssociateValueWith().
    // InitializeResources is a convenient place to call this.
    // This method is invoked only once per class, even though
    // it is an instance method.
    protected override void InitializeResources(StyleSet classStyleSet)
    {
      base.InitializeResources(classStyleSet);
      AssociateValueWith(this.Store, Wire.IsDirectedDomainPropertyId);
      // Add other properties here.
    }
}

AssociateValueWith() sollte für jede Domäneneigenschaft, die Sie registrieren möchten, einmal aufgerufen werden. Danach rufen alle Änderungen an der angegebenen Eigenschaft OnAssociatedPropertyChanged() in allen Formen auf, die das Modellelement der Eigenschaft darstellen.

Es ist nicht erforderlich, AssociateValueWith() für jede Instanz aufzurufen. Obwohl InitializeResources eine Instanzmethode ist, wird sie nur einmal für jede Formklasse aufgerufen.