Поделиться через


Настройка окно свойств

Вы можете настроить внешний вид и поведение окна свойств на языке, определенном для домена (DSL), в Visual Studio. В определении DSL вы определяете свойства домена для каждого класса домена. По умолчанию при выборе экземпляра класса на схеме или в модели Обозреватель каждое свойство домена отображается в окне свойств. Это позволяет просматривать и изменять значения свойств домена, даже если они не сопоставлены с полями фигур на схеме.

Имена, описания и категории

Имя и отображаемое имя. В определении свойства домена отображаемое имя свойства — это имя, которое отображается во время выполнения в окне свойств. Напротив, имя используется при написании кода программы для обновления свойства. Имя должно быть правильным буквенно-цифровым именем СРЕДЫ CLR, но отображаемое имя может содержать пробелы.

При установке имени свойства в определении DSL его отображаемое имя автоматически устанавливается на копию имени. При написании регистрируемого имени Pascal, например "FuelGauge", отображаемое имя будет автоматически содержать пробел: "Датчик топлива". Однако вы можете явно задать отображаемое имя другим значением.

Описание. Описание свойства домена отображается в двух местах:

  • В нижней части окна свойств, когда пользователь выбирает свойство. Его можно использовать для объяснения пользователю, что представляет свойство.

  • В созданном коде программы. Если вы используете средства документации по API для извлечения документации по API, оно будет отображаться как описание этого свойства в API.

Категория. Категория — это заголовок в окно свойств.

Предоставление возможностей стиля

Некоторые динамические функции графических элементов могут представляться или предоставляться как свойства домена. Функция, которая была представлена таким образом, может быть обновлена пользователем и может быть легко обновлена кодом программы.

Щелкните правой кнопкой мыши класс фигуры в определении DSL, наведите указатель на добавление предоставляемых объектов и выберите функцию.

На фигурах можно предоставлять свойства FillColor, OutlineColor, TextColor, OutlineDashStyle, OutlineThickness и FillGradientMode. В соединителях можно предоставлять свойства Color,TextColor, DashStyle и Толщины. На схемах можно предоставить свойства FillColor и TextColor .

Когда пользователь DSL выбирает элемент в модели, свойства этого элемента отображаются в окне свойств. Однако можно также отобразить свойства указанных связанных элементов. Это полезно, если вы определили группу элементов, которые работают вместе. Например, можно определить основной элемент и необязательный элемент подключаемого модуля. Если основной элемент сопоставляется с фигурой, а другой нет, полезно увидеть все их свойства, как если бы они были на одном элементе.

Этот эффект называется перенаправлением свойств, и это происходит автоматически в нескольких случаях. В других случаях можно добиться перенаправления свойств, определив дескриптор типа домена.

Варианты пересылки свойств по умолчанию

Когда пользователь выбирает фигуру или соединитель или элемент в Обозреватель, в окно свойств отображаются следующие свойства:

  • Свойства домена, определенные в классе домена элемента модели, включая те, которые определены в базовых классах. Исключение — это свойства домена, для которых задано значение "Просмотр".False

  • Имена элементов, связанных через связи с кратностью 0.1. Это обеспечивает удобный способ просмотра необязательных связанных элементов, даже если вы не определили сопоставление соединителей для связи.

  • Свойства домена для связи внедрения, предназначенной для элемента. Так как отношения внедрения обычно не отображаются явным образом, это позволяет пользователю видеть их свойства.

  • Свойства домена, определенные на выбранной фигуре или соединителе.

Добавление перенаправления свойств

Чтобы перенаправить свойство, определите дескриптор типа домена. Если у вас есть отношение к домену между двумя классами домена, можно использовать дескриптор типа домена, чтобы задать свойство домена в первом классе значение свойства домена во втором классе домена. Например, если у вас есть связь между классом домена Book и классом домена Author, можно использовать дескриптор типа домена, чтобы сделать свойство Name автора книги отображается в окно свойств, когда пользователь выбирает книгу.

Примечание.

Переадресация свойств влияет только на окно свойств, когда пользователь редактируется модель. Он не определяет свойство домена в принимающем классе. Если вы хотите получить доступ к свойству пересылаемого домена в других частях определения DSL или в коде программы, необходимо получить доступ к элементу пересылки.

В следующей процедуре предполагается, что вы создали DSL. Первые несколько шагов обобщают предварительные требования.

Переадресация свойства из другого элемента

  1. Создайте решение для языка для конкретного домена, содержащее по крайней мере два класса, которые в этом примере называются книгой и автором. Между книгой и автором должна быть связь любого вида.

    Кратность исходной роли (роль на стороне книги ) должна быть 0.1 или 1.1, чтобы каждая книга была одним автором.

  2. В Обозреватель DSL щелкните правой кнопкой мыши класс домена Book, а затем нажмите кнопку Add New DomainTypeDescriptor.

    Узел с именем Paths of Custom Property Descriptors отображается под узлом дескриптора пользовательского типа.

  3. Щелкните правой кнопкой мыши узел дескриптора пользовательского типа и нажмите кнопку "Добавить новое свойствоPath".

    Новый путь к свойству отображается в узле "Пути пользовательских дескрипторов свойств".

  4. Выберите новый путь к свойству, а в окне "Свойства " задайте для свойства путь к соответствующему элементу модели.

    Путь можно изменить в представлении дерева, щелкнув стрелку вниз справа от этого свойства. Дополнительные сведения о путях к домену см. в разделе "Синтаксис пути к домену". Когда вы редактировали его, путь должен выглядеть как BookReferencesAuthor.Author/! Автор.

  5. Задайте свойству"Имя домена" объекта Author.

  6. Задайте отображаемое имя для имени автора.

  7. Преобразование всех шаблонов, сборка и запуск DSL.

  8. На схеме модели создайте книгу, автора и свяжите их с помощью ссылочной связи. Выберите элемент книги, а в окно свойств вы увидите имя автора в дополнение к свойствам книги. Измените имя связанного автора или свяжите книгу с другим автором и обратите внимание, что имя автора книги изменяется.

Редакторы настраиваемых свойств

Окно свойств предоставляет соответствующий интерфейс редактирования по умолчанию для типа каждого свойства домена. Например, для перечисленного типа пользователь видит раскрывающийся список, а для числового свойства пользователь может ввести цифры. Это верно только для встроенных типов. Если указать внешний тип, пользователь сможет просмотреть значения свойства, но не изменять его.

Однако можно указать следующие редакторы и типы:

  1. Другой редактор, используемый со стандартным типом. Например, можно указать редактор пути к файлу для свойства строки.

  2. Внешний тип для свойства домена и редактор для него.

  3. Редактор .NET, например редактор пути к файлу или можно создать собственный редактор настраиваемых свойств.

    Преобразование между внешним типом и типом, например String, который имеет редактор по умолчанию.

    В DSL внешний тип — это любой тип , который не является одним из простых типов (например, boolean или Int32) или String.

Определение свойства домена с внешним типом

  1. В Обозреватель решений добавьте ссылку на сборку (DLL), содержащую внешний тип в проекте Dsl.

    Сборка может быть сборкой .NET или сборкой, предоставленной вами.

  2. Добавьте тип в список типов доменов , если это еще не сделано.

    1. Откройте dslDefinition.dsl и в Обозреватель DSL щелкните правой кнопкой мыши корневой узел и нажмите кнопку "Добавить новый внешний тип".

      Новая запись появится в узле "Типы доменов ".

      Предупреждение

      Элемент меню находится на корневом узле DSL, а не на узле типов доменов .

    2. Задайте имя и пространство имен нового типа в окно свойств.

  3. Обычно добавьте свойство домена в класс домена.

    В окно свойств выберите внешний тип из раскрывающегося списка в поле "Тип".

    На этом этапе пользователи могут просматривать значения свойства, но не могут изменять его. Отображаемые значения получаются из ToString() функции. Можно написать код программы, который задает значение свойства, например в команде или правиле.

Установка редактора свойств

Добавьте атрибут CLR в свойство домена в следующей форме:

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

Атрибут можно задать для свойства с помощью записи пользовательского атрибута в окно свойств.

Тип AnEditor должен быть производным от типа, указанного во втором параметре. Второй параметр должен быть либоUITypeEditor.ComponentEditor Дополнительные сведения см. в разделе EditorAttribute.

Вы можете указать собственный редактор или редактор .NET, например FileNameEditor или ImageEditor. Например, используйте следующую процедуру, чтобы иметь свойство, в котором пользователь может ввести имя файла.

Определение свойства домена имени файла

  1. Добавьте свойство домена в класс домена в определении DSL.

  2. Выберите новое свойство. В поле "Настраиваемый атрибут" в окно свойств введите следующий атрибут. Чтобы ввести этот атрибут, щелкните многоточие [...], а затем введите имя атрибута и параметры отдельно:

    [System.ComponentModel.Editor (
       typeof(System.Windows.Forms.Design.FileNameEditor)
       , typeof(System.Drawing.Design.UITypeEditor))]
    
    
  3. Оставьте тип свойства домена в параметре String по умолчанию.

  4. Чтобы проверить редактор, убедитесь, что пользователи могут открыть редактор имен файлов для изменения свойства домена.

    1. Нажмите клавиши CTRL+F5 или F5. В решении отладки откройте тестовый файл. Создайте элемент класса домена и выберите его.

    2. В окно свойств выберите свойство домена. Поле значения показывает многоточие [...].

    3. Щелкните многоточие. Откроется диалоговое окно файла. Выберите файл и закройте диалоговое окно. Путь к файлу теперь является значением свойства домена.

Определение собственного редактора свойств

Вы можете определить собственный редактор. Это позволит пользователю изменять определенный тип или изменять стандартный тип особым образом. Например, можно разрешить пользователю вводить строку, представляющую формулу.

Вы определяете редактор, написав класс, производный от UITypeEditor. Класс должен переопределить:

  • EditValue, чтобы взаимодействовать с пользователем и обновлять значение свойства.

  • GetEditStyle, чтобы указать, откроется ли в редакторе диалоговое окно или в раскрывающемся меню.

Вы также можете предоставить графическое представление значения свойства, которое будет отображаться в сетке свойств. Для этого переопределите GetPaintValueSupportedи PaintValue. Дополнительные сведения см. в разделе UITypeEditor.

Примечание.

Добавьте код в отдельный файл кода в проекте Dsl .

Например:

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

Чтобы использовать этот редактор, задайте для пользовательского атрибута свойства домена следующее:

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

Дополнительные сведения см. в разделе UITypeEditor.

Укажите раскрывающийся список значений

Список значений для пользователя можно указать.

Примечание.

Этот метод содержит список значений, которые могут изменяться во время выполнения. Если вы хотите указать список, который не изменяется, рекомендуется использовать перечислимый тип в качестве типа свойства домена.

Чтобы определить список стандартных значений, добавьте в свойство домена атрибут CLR, имеющий следующую форму:

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

Определите класс, производный от класса TypeConverter. Добавьте код в отдельный файл в проекте Dsl . Например:

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

}