Anpassen der Eigenschaftenfenster

Sie können die Darstellung und das Verhalten des Eigenschaftenfensters in Ihrer domänenspezifischen Sprache (DSL) in Visual Studio. In Ihrer DSL-Definition definieren Sie Domäneneigenschaften für jede Domänenklasse. Wenn Sie eine Instanz der -Klasse in einem Diagramm oder im Modell-Explorer auswählen, wird standardmäßig jede Domäneneigenschaft im Eigenschaftenfenster aufgeführt. Auf diese Weise können Sie die Werte von Domäneneigenschaften anzeigen und bearbeiten, auch wenn Sie sie nicht den Formfeldern im Diagramm zugeordnet haben.

Namen, Beschreibungen und Kategorien

Name und Anzeigename. In ihrer Definition einer Domäneneigenschaft ist der Anzeigename der Eigenschaft der Name, der zur Laufzeit im Eigenschaftenfenster angezeigt wird. Im Gegensatz dazu wird der Name verwendet, wenn Sie Programmcode schreiben, um die Eigenschaft zu aktualisieren. Der Name muss ein korrekter alphanumerischer CLR-Name sein, der Anzeigename kann jedoch Leerzeichen enthalten.

Wenn Sie den Namen einer Eigenschaft in der DSL-Definition festlegen, wird der Anzeigename automatisch auf eine Kopie des Namens festgelegt. Wenn Sie einen Pascal-Case-Namen wie z.B. "FuelDisplayge" schreiben, enthält der Anzeigename automatisch ein Leerzeichen: "Fuel Gauge". Sie können den Anzeigenamen jedoch explizit auf einen anderen Wert festlegen.

Beschreibung. Die Beschreibung einer Domäneneigenschaft wird an zwei Stellen angezeigt:

  • Am unteren Rand des Eigenschaftenfensters, wenn der Benutzer die Eigenschaft auswählt. Sie können es verwenden, um dem Benutzer zu erklären, was die Eigenschaft darstellt.

  • Im generierten Programmcode. Wenn Sie die Dokumentationseinrichtung zum Extrahieren der API-Dokumentation verwenden, wird sie als Beschreibung dieser Eigenschaft in der API angezeigt.

Kategorie Eine Kategorie ist eine Überschrift im Eigenschaftenfenster.

Verfügbar machen von Stilfeatures

Einige der dynamischen Features von grafischen Elementen können als Domäneneigenschaften dargestellt oder verfügbar gemacht werden. Ein Feature, das auf diese Weise verfügbar gemacht wurde, kann vom Benutzer aktualisiert werden und kann einfacher durch Programmcode aktualisiert werden.

Klicken Sie in der DSL-Definition mit der rechten Maustaste auf eine Shape-Klasse, zeigen Sie auf Verfügbar gemacht hinzufügen, und wählen Sie dann ein Feature aus.

Bei Formen können Sie die Eigenschaften FillColor, OutlineColor, TextColor, OutlineDashStyle, OutlineThickness und FillGradientMode verfügbar machen. Bei Connectors können Sie die Eigenschaften , Color TextColor, DashStyle und Thickness verfügbar machen. In Diagrammen können Sie die Eigenschaften FillColor und TextColor verfügbar machen.

Wenn der Benutzer Ihrer DSL ein Element in einem Modell auswählt, werden die Eigenschaften dieses Elements im Eigenschaftenfenster angezeigt. Sie können jedoch auch die Eigenschaften der angegebenen verknüpften Elemente anzeigen. Dies ist nützlich, wenn Sie eine Gruppe von Elementen definiert haben, die zusammenarbeiten. Beispielsweise können Sie ein Hauptelement und ein optionales Plug-In-Element definieren. Wenn das Hauptelement einer Form zugeordnet ist und das andere nicht, ist es hilfreich, alle eigenschaften so zu sehen, als ob sie sich auf einem Element befingen.

Dieser Effekt heißt Eigenschaftenweiterleitung und tritt in mehreren Fällen automatisch auf. In anderen Fällen können Sie die Eigenschaftenweiterleitung erreichen, indem Sie einen Domänentypdeskriptor definieren.

Standardfälle für die Eigenschaftenweiterleitung

Wenn der Benutzer eine Form, einen Konnektor oder ein Element im Explorer auswählt, werden die folgenden Eigenschaften in der Eigenschaftenfenster:

  • Die Domäneneigenschaften, die für die Domänenklasse des Modellelements definiert sind, einschließlich der in Basisklassen definierten Eigenschaften. Eine Ausnahme sind Domäneneigenschaften, für die Sie Is Browsable auf festgelegt False haben.

  • Die Namen von Elementen, die über Beziehungen verknüpft sind, die eine Multiplicität von 0..1 haben. Dies bietet eine praktische Methode, optional verknüpfte Elemente zu sehen, auch wenn Sie keine Connectorzuordnung für die Beziehung definiert haben.

  • Domäneneigenschaften der Einbettungsbeziehung, die auf das Element zielt. Da Einbettungsbeziehungen in der Regel nicht explizit angezeigt werden, können Benutzer ihre Eigenschaften anzeigen.

  • Domäneneigenschaften, die für die ausgewählte Form oder den ausgewählten Connector definiert sind.

Hinzufügen der Eigenschaftenweiterleitung

Zum Weitergeleitet einer Eigenschaft definieren Sie einen Domänentypdeskriptor. Wenn Sie über eine Domänenbeziehung zwischen zwei Domänenklassen verfügen, können Sie einen Domänentypdeskriptor verwenden, um eine Domäneneigenschaft in der ersten Klasse auf den Wert einer Domäneneigenschaft in der zweiten Domänenklasse zu setzen. Wenn Sie beispielsweise eine Beziehung zwischen einer Book-Domänenklasse und einer Author-Domänenklasse haben, können Sie einen Domänentypdeskriptor verwenden, damit die Name-Eigenschaft eines Buchautors in der Eigenschaftenfenster angezeigt wird, wenn der Benutzer das Buch auswählt.

Hinweis

Die Eigenschaftenweiterleitung wirkt sich nur auf Eigenschaftenfenster, wenn der Benutzer ein Modell bearbeitet. Es wird keine Domäneneigenschaft für die empfangende Klasse definiert. Wenn Sie auf die weitergeleitete Domäneneigenschaft in anderen Teilen der DSL-Definition oder im Programmcode zugreifen möchten, müssen Sie auf das Weiterleitungselement zugreifen.

Im folgenden Verfahren wird davon ausgegangen, dass Sie eine DSL erstellt haben. In den ersten Schritten werden die Voraussetzungen zusammengefasst.

Eine Eigenschaft von einem anderen Element weiter

  1. Erstellen Sie Domänenspezifische Sprachtools eine Projektmappe, die mindestens zwei Klassen enthält, die in diesem Beispiel Book und Author heißen. Es sollte eine Beziehung einer der beiden Arten zwischen Book und Author geben.

    Die Multiplicität der Quellrolle (die Rolle auf der Book-Seite) sollte 0..1 oder 1..1 sein, sodass jedes Buch über einen Autor verfügt.

  2. Klicken Sie im DSL-Explorer mit der rechten Maustaste auf die Domänenklasse Book, und klicken Sie dann auf Add New DomainTypeDescriptor.

    Unter dem Knoten Benutzerdefinierte Typdeskriptor wird ein Knoten mit dem Namen Pfade benutzerdefinierter Eigenschaftendeskriptoren angezeigt.

  3. Klicken Sie mit der rechten Maustaste auf den Knoten Benutzerdefinierte Typbeschreibung, und klicken Sie dann auf Neue Eigenschaft hinzufügenPfad.

    Unter dem Knoten Pfade benutzerdefinierter Eigenschaftendeskriptoren wird ein neuer Eigenschaftenpfad angezeigt.

  4. Wählen Sie den neuen Eigenschaftenpfad aus, und legen Sie im Eigenschaftenfenster Pfad auf Eigenschaft auf den Pfad des entsprechenden Modellelements fest.

    Sie können den Pfad in einer Strukturansicht bearbeiten, indem Sie auf den Pfeil nach unten rechts neben dieser Eigenschaft klicken. Weitere Informationen zu Domänenpfaden finden Sie unter Domänenpfadsyntax. Wenn Sie ihn bearbeitet haben, sollte der Pfad bookReferencesAuthor.Author/! ähneln. Erstellen Sie.

  5. Legen Sie Property auf die Name-Domäneneigenschaft von Author fest.

  6. Legen Sie Anzeigename auf Autorname fest.

  7. Transformieren Sie alle Vorlagen, erstellen Sie die DSL, und führen Sie sie aus.

  8. Erstellen Sie in einem Modelldiagramm ein Buch, einen Autor, und verknüpfen Sie sie mithilfe der Verweisbeziehung. Wählen Sie das Book-Element aus, und Eigenschaftenfenster neben den Eigenschaften des Buchs der Name des Autors. Ändern Sie den Namen des verknüpften Autors, oder verknüpfen Sie das Buch mit einem anderen Autor, und beobachten Sie, dass sich der Autorname des Buchs ändert.

Benutzerdefinierte Eigenschaften-Editoren

Das Eigenschaftenfenster bietet eine geeignete Standardbearbeitungserfahrung für den Typ der einzelnen Domäneneigenschaft. Für einen aufzählten Typ wird dem Benutzer beispielsweise eine Dropdownliste angezeigt, und für eine numerische Eigenschaft kann der Benutzer Ziffern eingeben. Dies gilt nur für die integrierten Typen. Wenn Sie einen externen Typ angeben, kann der Benutzer die Werte der Eigenschaft sehen, aber nicht bearbeiten.

Sie können jedoch die folgenden Editoren und Typen angeben:

  1. Ein anderer Editor, der mit einem Standardtyp verwendet wird. Sie können beispielsweise einen Dateipfad-Editor für eine Zeichenfolgeneigenschaft angeben.

  2. Ein externer Typ für die Domäneneigenschaft und ein Editor dafür.

  3. Ein .NET-Editor, z. B. der Dateipfad-Editor, oder Sie können einen eigenen benutzerdefinierten Eigenschaften-Editor erstellen.

    Eine Konvertierung zwischen einem externen Typ und einem Typ wie String, der über einen Standard-Editor verfügt.

    In einer DSL ist ein externer Typ ein beliebiger Typ, der nicht einer der einfachen Typen (z. B. Boolean oder Int32) oder String ist.

Definieren einer Domäneneigenschaft mit einem externen Typ

  1. Fügen Projektmappen-Explorer im DSL-Projekt einen Verweis auf die Assembly (DLL) hinzu, die den externen Typ enthält.

    Die Assembly kann eine .NET-Assembly oder eine von Ihnen bereitgestellte Assembly sein.

  2. Fügen Sie den Typ der Liste Domänentypen hinzu, sofern Sie dies nicht bereits getan haben.

    1. Öffnen Sie dslDefinition.dsl, klicken Sie im DSL-Explorer mit der rechten Maustaste auf den Stammknoten, und klicken Sie dann auf Neuen externen Typ hinzufügen.

      Unter dem Knoten Domänentypen wird ein neuer Eintrag angezeigt.

      Warnung

      Das Menüelement befindet sich auf dem DSL-Stammknoten, nicht auf dem Knoten Domänentypen.

    2. Legen Sie den Namen und den Namespace des neuen Typs im Eigenschaftenfenster.

  3. Fügen Sie einer Domänenklasse wie gewohnt eine Domäneneigenschaft hinzu.

    Wählen Sie Eigenschaftenfenster in der Dropdownliste im Feld Typ den externen Typ aus.

    In dieser Phase können Benutzer die Werte der Eigenschaft anzeigen, aber nicht bearbeiten. Die angezeigten Werte werden aus der -Funktion ToString() ermittelt. Sie können Programmcode schreiben, der den Wert der Eigenschaft fest legt, z. B. in einem Befehl oder einer Regel.

Festlegen eines Eigenschaften-Editors

Fügen Sie der Domäneneigenschaft ein CLR-Attribut in der folgenden Form hinzu:

[System.ComponentModel.Editor (
   typeof(AnEditor),
   typeof(System.Drawing.Design.UITypeEditor))]

Sie können das Attribut für eine Eigenschaft festlegen, indem Sie den Eintrag Benutzerdefiniertes Attribut in der Eigenschaftenfenster.

Der Typ von AnEditor muss von dem im zweiten Parameter angegebenen Typ abgeleitet werden. Der zweite Parameter sollte entweder oder UITypeEditor ComponentEditor sein. Weitere Informationen finden Sie unter EditorAttribute.

Sie können einen eigenen Editor oder einen .NET-Editor angeben, z. B. FileNameEditor oder ImageEditor . Verwenden Sie beispielsweise das folgende Verfahren, um über eine -Eigenschaft zu verfügen, in die der Benutzer einen Dateinamen eingeben kann.

Definieren einer Dateinamendomäneneigenschaft

  1. Fügen Sie einer Domänenklasse in Ihrer DSL-Definition eine Domäneneigenschaft hinzu.

  2. Wählen Sie die neue Eigenschaft aus. Geben Sie im Feld Benutzerdefiniertes Attribut im Eigenschaftenfenster das folgende Attribut ein. Klicken Sie zum Eingeben dieses Attributs auf die Auslassungsellipse [...] , und geben Sie dann den Attributnamen und die Parameter separat ein:

    [System.ComponentModel.Editor (
       typeof(System.Windows.Forms.Design.FileNameEditor)
       , typeof(System.Drawing.Design.UITypeEditor))]
    
    
  3. Belasse den Typ der Domäneneigenschaft in der Standardeinstellung String.

  4. Um den Editor zu testen, stellen Sie sicher, dass Benutzer den Dateinamen-Editor öffnen können, um Ihre Domäneneigenschaft zu bearbeiten.

    1. Drücken Sie STRG+F5 oder F5. Öffnen Sie in der Debuglösung eine Testdatei. Erstellen Sie ein Element der Domänenklasse, und wählen Sie es aus.

    2. Wählen Sie Eigenschaftenfenster die Domäneneigenschaft aus. Das Wertfeld zeigt die Auslassungsellipse [...] an.

    3. Klicken Sie auf die Auslassungsellipse. Ein Dateidialogfeld wird angezeigt. Wählen Sie eine Datei aus, und schließen Sie das Dialogfeld. Der Dateipfad ist jetzt der Wert der Domäneneigenschaft.

Definieren eines eigenen Eigenschaften-Editors

Sie können einen eigenen Editor definieren. Sie würden dies tun, damit der Benutzer entweder einen von Ihnen definierten Typ bearbeiten oder einen Standardtyp auf besondere Weise bearbeiten kann. Beispielsweise können Sie dem Benutzer erlauben, eine Zeichenfolge eingibt, die eine Formel darstellt.

Sie definieren einen Editor, indem Sie eine Klasse schreiben, die von abgeleitet UITypeEditor ist. Die -Klasse muss Überschreiben:

  • EditValue, um mit dem Benutzer zu interagieren und den Eigenschaftswert zu aktualisieren.

  • GetEditStyle, um anzugeben, ob ihr Editor ein Dialogfeld öffnet oder ein Dropdownmenü an.

Sie können auch eine grafische Darstellung des Werts der Eigenschaft bereitstellen, der im Eigenschaftenraster angezeigt wird. Überschreiben Sie dazu GetPaintValueSupported , und PaintValue . Weitere Informationen finden Sie unter UITypeEditor.

Hinweis

Fügen Sie den Code in einer separaten Codedatei im DSL-Projekt hinzu.

Beispiel:

internal class TextFileNameEditor : System.Windows.Forms.Design.FileNameEditor
{
  protected override void InitializeDialog(System.Windows.Forms.OpenFileDialog openFileDialog)
  {
    base.InitializeDialog(openFileDialog);
    openFileDialog.Filter = "Text files(*.txt)|*.txt|All files (*.*)|*.*";
    openFileDialog.Title = "Select a text file";
  }
}

Um diesen Editor zu verwenden, legen Sie das benutzerdefinierte Attribut einer Domäneneigenschaft auf:

[System.ComponentModel.Editor (
   typeof(MyNamespace.TextFileNameEditor)
   , typeof(System.Drawing.Design.UITypeEditor))]

Weitere Informationen finden Sie unter UITypeEditor.

Bereitstellen einer Dropdownliste mit Werten

Sie können eine Liste von Werten bereitstellen, aus der ein Benutzer auswählen kann.

Hinweis

Dieses Verfahren enthält eine Liste von Werten, die sich zur Laufzeit ändern können. Wenn Sie eine Liste bereitstellen möchten, die sich nicht ändert, sollten Sie stattdessen einen aufzählten Typ als Typ Ihrer Domäneneigenschaft verwenden.

Um eine Liste von Standardwerten zu definieren, fügen Sie ihrer Domäneneigenschaft ein CLR-Attribut mit der folgenden Form hinzu:

[System.ComponentModel.TypeConverter
(typeof(MyTypeConverter))]

Definieren Sie eine Klasse, die sich von TypeConverter ableitet. Fügen Sie den Code in einer separaten Datei im Dsl-Projekt hinzu. Beispiel:

/// <summary>
/// Type converter that provides a list of values
/// to be displayed in the property grid.
/// </summary>
/// <remarks>This type converter returns a list
/// of the names of all "ExampleElements" in the
/// current store.</remarks>
public class MyTypeConverter : System.ComponentModel.TypeConverter
{
  /// <summary>
  /// Return true to indicate that we return a list of values to choose from
  /// </summary>
  /// <param name="context"></param>
  public override bool GetStandardValuesSupported
    (System.ComponentModel.ITypeDescriptorContext context)
  {
    return true;
  }

  /// <summary>
  /// Returns true to indicate that the user has
  /// to select a value from the list
  /// </summary>
  /// <param name="context"></param>
  /// <returns>If we returned false, the user would
  /// be able to either select a value from
  /// the list or type in a value that is not in the list.</returns>
  public override bool GetStandardValuesExclusive
      (System.ComponentModel.ITypeDescriptorContext context)
  {
    return true;
  }

  /// <summary>
  /// Return a list of the values to display in the grid
  /// </summary>
  /// <param name="context"></param>
  /// <returns>A list of values the user can choose from</returns>
  public override StandardValuesCollection GetStandardValues
      (System.ComponentModel.ITypeDescriptorContext context)
  {
    // Try to get a store from the current context
    // "context.Instance"  returns the element(s) that
    // are currently selected i.e. whose values are being
    // shown in the property grid.
    // Note that the user could have selected multiple objects,
    // in which case context.Instance will be an array.
    Store store = GetStore(context.Instance);

    List<string> values = new List<string>();

    if (store != null)
    {
      values.AddRange(store.ElementDirectory
        .FindElements<ExampleElement>()
        .Select<ExampleElement, string>(e =>
      {
        return e.Name;
      }));
    }
    return new StandardValuesCollection(values);
  }

  /// <summary>
  /// Attempts to get to a store from the currently selected object(s)
  /// in the property grid.
  /// </summary>
  private Store GetStore(object gridSelection)
  {
    // We assume that "instance" will either be a single model element, or
    // an array of model elements (if multiple items are selected).

    ModelElement currentElement = null;

    object[] objects = gridSelection as object[];
    if (objects != null && objects.Length > 0)
    {
      currentElement = objects[0] as ModelElement;
    }
    else
    {
        currentElement = gridSelection as ModelElement;
    }

    return (currentElement == null) ? null : currentElement.Store;
  }

}

Siehe auch