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


Создание языка для конкретного домена на основе Windows Forms

Windows Forms можно использовать для отображения состояния модели языка для конкретного домена (DSL), а не с помощью схемы DSL. В этом разделе описывается привязка Windows Form к DSL с помощью пакета SDK для визуализации и моделирования Visual Studio.

На следующем рисунке показан пользовательский интерфейс Windows Form и обозреватель моделей для экземпляра DSL:

DSL instance in Visual Studio

Создание DSL Windows Forms

Шаблон DSL конструктора WinForm создает минимальный DSL, который можно изменить в соответствии с вашими собственными требованиями.

  1. Создайте DSL из шаблона Минимального конструктора WinForm.

    В этом пошаговом руководстве предполагается следующее:

    • Имя решения и DSL: FarmApp
    • Пространство имен: Company.FarmApp
  2. Экспериментируйте с начальным примером, который предоставляет шаблон:

    1. Преобразование всех шаблонов.

    2. Создайте и запустите пример (CTRL+F5).

    3. В экспериментальном экземпляре Visual Studio откройте Sample файл в проекте отладки.

      Обратите внимание, что он отображается в элементе управления Windows Forms.

      Вы также можете просмотреть элементы модели, отображаемые в Обозреватель.

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

    В основном экземпляре Visual Studio обратите внимание на следующие моменты о решении DSL:

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

  • Dsl Помимо проектов и DslPackage проектов, решение содержит третий проект с именем UI.пользовательского интерфейса, содержащий определение элемента управления Windows Forms. DslPackageUIзависит от и UI зависит от Dsl.

  • DslPackage В проекте UI\DocView.cs содержит код, который отображает элемент управления Windows Forms, определенный UI в проекте.

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

    • Класс Windows Forms с именем ModelViewControl.

    • Файл с именем DataBinding.cs , содержащий дополнительное частичное определение ModelViewControl. Чтобы просмотреть его содержимое, в Обозреватель решений откройте контекстное меню для файла и выберите "Просмотреть код".

Сведения о проекте пользовательского интерфейса

При обновлении файла определения DSL для определения собственного UI DSL необходимо обновить элемент управления в проекте, чтобы отобразить DSL. Dsl В отличие от проектов, DslPackage пример UI проекта не создается из DslDefinitionl.dsl. Вы можете добавить TT-файлы для создания кода, если требуется, хотя это не рассматривается в этом пошаговом руководстве.

Обновление определения DSL

Ниже приведено определение DSL, используемое в этом пошаговом руководстве.

DSL definition

  1. Откройте dslDefinition.dsl в конструкторе DSL.

  2. Удаление ExampleElement

  3. Переименуйте класс домена ExampleModel в Farm.

    Присвойте ему дополнительные свойства домена с именем Size типа Int32 и IsOrganic типа Boolean.

    Примечание.

    Если удалить корневой класс домена и создать новый корневой каталог, необходимо сбросить свойство "Корневой класс редактора". В Обозреватель DSL выберите редактор. Затем в окно свойств задайте для корневого класса Farmзначение .

  4. Используйте средство именованного класса домена для создания следующих классов домена:

    • Field — присвойте этому дополнительному свойству домена имя Size.

    • Animal— В окно свойств задайте для модификатора наследования значение Abstract.

    Примечание.

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

  5. Используйте средство класса домена для создания следующих классов:

    • Sheep

    • Goat

  6. Используйте средство наследования для создания Goat и Sheep наследованияAnimal.

  7. Используйте средство Field внедрения и Animal подFarm.

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

  9. Преобразование всех шаблонов на панели инструментов Обозреватель решений.

  10. Создайте проект Dsl.

    Примечание.

    На этом этапе другие проекты не будут создаваться без ошибок. Однако мы хотим создать проект Dsl, чтобы его сборка была доступна мастеру источника данных.

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

Теперь вы можете создать новый пользовательский элемент управления, который будет отображать сведения, хранящиеся в модели DSL. Самый простой способ подключения пользовательского элемента управления к модели — через привязки данных. Тип адаптера привязки данных с именем ModelingBindingSource специально предназначен для подключения DSLs к интерфейсам, отличным от VMSDK.

Определение модели DSL в качестве источника данных

  1. В меню "Данные" выберите "Показать источники данных".

    Открывается окно Источники данных.

    Нажмите кнопку "Добавить новый источник данных". Открывается мастер настройки источника данных.

  2. Нажмите кнопку "Объект", "Далее".

    Разверните dsl, Company.FarmApp и выберите Farm, который является корневым классом модели. Нажмите кнопку Готово.

    В Обозреватель решений проект пользовательского интерфейса теперь содержит свойства\DataSources\Farm.datasource

    Свойства и связи класса модели отображаются в окне источников данных.

    Data sources window

Подключение модель в форму

  1. В проекте пользовательского интерфейса удалите все существующие CS-файлы.

  2. Добавьте новый файл пользовательского элемента управления с именем FarmControl в проект пользовательского интерфейса .

  3. В окне "Источники данных" в раскрывающемся меню фермы выберите "Сведения".

    Оставьте параметры по умолчанию для других свойств.

  4. Откройте FarmControl.cs в представлении конструктора.

    Перетащите ферму из окна источников данных в FarmControl.

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

  5. Удаление farmBindingNavigator. Это также автоматически создается в конструкторе FarmControl , но это не полезно для этого приложения.

  6. С помощью панели элементов создайте два экземпляра DataGridView и назовите их AnimalGridView и FieldGridView.

    Примечание.

    Альтернативным шагом является перетаскивание элементов "Животные и поля" из окна источников данных в элемент управления. Это действие автоматически создает сетки данных и привязки между представлением сетки и источником данных. Однако эта привязка не работает правильно для DSLs. Поэтому лучше создать сетки данных и привязки вручную.

  7. Если панель элементов не содержит инструмент ModelingBindingSource , добавьте его. В контекстном меню вкладки "Данные " выберите пункт " Выбрать элементы". В диалоговом окне "Выбор элементов панели элементов" выберите ModelingBindingSource на вкладке платформа .NET Framework.

  8. С помощью панели элементов создайте два экземпляра ModelingBindingSource и назовите их AnimalBinding и FieldBinding.

  9. Задайте свойству DataSource каждого ModelingBindingSource значение farmBindingSource.

    Задайте для свойства DataMember значение "Животные" или "Поля".

  10. Задайте для свойств AnimalBindingAnimalGridView DataSource значение и FieldGridView значение FieldBinding.

  11. Настройте макет элемента управления Farm в соответствии с вашим вкусом.

    ModelingBindingSource — это адаптер, который выполняет несколько функций, относящихся к DSLs:

  • Он упаковывает обновления в транзакцию хранилища VMSDK.

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

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

    Schema of the DSL binding

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

Завершение привязок к DSL

  1. Добавьте следующий код в отдельный файл кода в проекте пользовательского интерфейса :

    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. В проекте DslPackage измените DslPackage\DocView.tt, чтобы обновить следующее определение переменной:

    string viewControlTypeName = "FarmControl";
    

Проверка DSL

Теперь решение DSL может создавать и запускаться, хотя вам может потребоваться добавить дальнейшие улучшения позже.

  1. Выполните сборку и запуск решения.

  2. В экспериментальном экземпляре Visual Studio откройте образец файла.

  3. В Обозреватель FarmApp откройте контекстное меню на корневом узле фермы и нажмите кнопку "Добавить новый коз".

    Goat1 отображается в представлении "Животные ".

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

    Контекстное меню необходимо использовать на узле Фермы , а не на узле "Животные ".

  4. Выберите корневой узел фермы и просмотрите его свойства.

    В представлении формы измените имя или размер фермы.

    При переходе от каждого поля в форме соответствующее свойство изменяется в окно свойств.

Улучшение DSL

Немедленное обновление свойств

  1. В представлении конструктора FarmControl.cs выберите простое поле, например Name, Size или IsOrganic.

  2. В окно свойств разверните dataBindings и откройте (дополнительно).

    В диалоговом окне "Форматирование и расширенная привязка" в разделе "Режим обновления источника данных" выберите OnPropertyChanged.

  3. Выполните сборку и запуск решения.

    Убедитесь, что при изменении содержимого поля соответствующее свойство модели фермы изменяется немедленно.

Предоставление кнопок "Добавить"

  1. В представлении конструктора FarmControl.cs используйте панель элементов для создания кнопки в форме.

    Измените имя и текст кнопки, например New Sheep.

  2. Откройте код за кнопкой (например, дважды щелкнув его).

    Измените его следующим образом:

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

    Вам также потребуется вставить следующую директиву:

    
    using Microsoft.VisualStudio.Modeling;
    
  3. Добавьте аналогичные кнопки для коз и полей.

  4. Выполните сборку и запуск решения.

  5. Убедитесь, что новая кнопка добавляет элемент. Новый элемент должен отображаться как в FarmApp Обозреватель, так и в соответствующем представлении сетки данных.

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

    Sample data grid view

Сведения о коде для добавления элемента

Для кнопок нового элемента следующий альтернативный код немного проще.

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

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

Поэтому рекомендуется ElementOperations создавать новые элементы. Дополнительные сведения см. в разделе "Настройка создания и перемещения элементов".