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


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

В Visual Studio Ultimate можно определить дополнительные пункты меню, которые отображаются, когда пользователь щелкает UML-схему правой кнопкой мыши. Можно управлять отображением команды меню и ее появлением по щелчку пользователя правой кнопкой мыши любого элемента на схеме. Кроме того, можно создать код, который будет выполняться при выборе пользователем пункта меню. Эти расширения можно упаковать в расширении интеграции Visual Studio (VSIX) и распространить их среди других пользователей Visual Studio Ultimate.

Требования

Определение команды меню

Чтобы создать команду меню для конструктора UML, необходимо создать класс, определяющий поведение команды, и внедрить этот класс в расширение Visual Studio Integration Extension (VSIX). Расширение VSIX выполняет роль контейнера, позволяющего установить команду. Предусмотрено два альтернативных способа определения команды меню.

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

  • Создайте отдельную команду меню и проекты VSIX. Этот метод следует использовать, если требуется объединить несколько типов расширений в одном VSIX-файле. Например, если для команды меню требуется, чтобы в модели соблюдались определенные ограничения, команду меню можно внедрить в то же расширение VSIX, что и метод проверки.

Создание команды меню в ее собственном расширении VSIX

  1. В диалоговом окне Создать проект в разделе Проекты моделирования выберите Расширение команды.

  2. Откройте файл .cs в новом проекте и внесите в класс CommandExtension изменения, реализующие команду.

    Дополнительные сведения см. в разделе Реализация команды меню.

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

  4. Проверьте команду меню, нажав клавишу F5. Дополнительные сведения см. в разделе Выполнение команды меню.

  5. Установите команду меню на другой компьютер, скопировав файл bin\*\*.vsix, построенный вашим проектом. Дополнительные сведения см. в разделе Установка команды меню.

Создание отдельной команды меню в проекте библиотеки классов (DLL)

  1. Создайте проект библиотеки классов либо в новом, либо в существующем решении Visual Studio.

    1. В меню Файл выберите пункт Создать, а затем команду Проект.

    2. В разделе Установленные шаблоны выберите узел Visual C# или Visual Basic. В центральном столбце щелкните Библиотека классов.

    3. В поле Решение выберите, нужно ли создать новое решение или добавить компонент в уже открытое решение VSIX.

    4. Задайте имя и расположение проекта и нажмите кнопку ОК.

  2. В проекте добавьте ссылки на следующее.

    Ссылка

    Возможности

    System.ComponentModel.Composition

    Определять компоненты с использованием Managed Extensibility Framework (MEF).

    Microsoft.VisualStudio.Uml.Interfaces

    Читать и изменять свойства элементов модели.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Создавать элементы модели, изменять фигуры на схемах.

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Определять обработчики событий модели.

    Инкапсулировать ряды изменений в модель. Дополнительные сведения см. в разделе Практическое руководство. Связывание обновлений модели с использованием транзакций.

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.10.0

    (не всегда необходимо)

    Осуществлять доступ к дополнительным элементам схемы для обработчиков жестов.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer

    Требуется только для команд на схемах слоев. Дополнительные сведения см. в разделе Создание расширений для схем слоев.

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

  3. Добавьте файл класса в проект со следующим кодом.

    Примечание

    Измените пространство имен, имя класса и значение, возвращаемое переменной Text, в соответствии с вашими предпочтениями.

    using System.ComponentModel.Composition;   
    using System.Linq;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
    using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
    using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
    using Microsoft.VisualStudio.Uml.Classes; 
        // ADD other UML namespaces if required
    
    namespace UMLmenu1 // CHANGE
    {
      // DELETE any of these attributes if the command
      // should not appear in some types of diagram.
      [ClassDesignerExtension]
      [ActivityDesignerExtension]
      [ComponentDesignerExtension]
      [SequenceDesignerExtension]
      [UseCaseDesignerExtension]
      // [LayerDesignerExtension] // if you have installed Feature Pack 1
    
      // All menu commands must export ICommandExtension:
      [Export (typeof(ICommandExtension))]
      // CHANGE class name
      public class Menu1 : ICommandExtension
      {
        [Import]
        public IDiagramContext DiagramContext { get; set; }
    
        public void QueryStatus(IMenuCommand command)
        { // Set command.Visible or command.Enabled to false
          // to disable the menu command.
          command.Visible = command.Enabled = true;
        }
    
        public string Text
        {
          get { return "MENU COMMAND LABEL"; }
        }
    
        public void Execute(IMenuCommand command)
        {
          // A selection of starting points:
          IDiagram diagram = this.DiagramContext.CurrentDiagram;
          foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>())
          { IElement element = shape.Element; }
          IModelStore modelStore = diagram.ModelStore;
          IModel model = modelStore.Root;
          foreach (IElement element in modelStore.AllInstances<IClass>()) 
          { }
        }
      }
    }
    

    Дополнительные сведения о реализации методов см. в разделе Реализация команды меню.

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

Добавление отдельной команды меню в проект VSIX

  1. Эта операция не требуется, если команда меню создана со своим собственным расширением VSIX.

  2. Создайте проект VSIX, если ваше решение еще его не содержит.

    1. В окне Обозреватель решений щелкните правой кнопкой мыши решение, выберите Add, затем щелкните Новый проект.

    2. В разделе Установленные шаблоны разверните узелVisual C# или Visual Basic, а затем выберите пункт Расширение среды. В среднем столбце щелкните Проект VSIX.

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

    В обозревателе решений щелкните правой кнопкой мыши проект VSIX, затем щелкните Назначить запускаемым проектом.

  4. Последовательно выберите source.extension.vsixmanifest, Содержимое, затем добавьте проект библиотеки классов в качестве компонента MEF.

    1. Откройте source.extension.vsixmanifest.

    2. Щелкните Добавить содержимое.

    3. В поле Выбор типа содержимого выберите MEF Component.

    4. В списке Выбор источника щелкните Проект и выберите имя проекта библиотеки классов.

  5. Щелкните Выбрать выпуски и выберите выпуски Visual Studio, на которых следует запускать расширение.

  6. Задайте имя и поля описания VSIX. Сохраните файл.

Реализация команды меню

Класс команды меню реализует методы, обязательные для объекта ICommandExtension.

string Text { get; }

Возвращение метки пункта меню.

void QueryStatus(IMenuCommand command);

Вызывается, если щелкнуть в области схемы правой кнопкой мыши.

Этот метод не должен изменять модель.

Используйте DiagramContext.CurrentDiagram.SelectedShapes, чтобы определить, нужно ли отображать и включать команду.

Задайте

  • для command.Visible значение true, если команда должна отображаться в меню по щелчку схемы правой кнопкой мыши.

  • command.Enabled значение true, если пользователь может щелкнуть команду в меню.

  • command.Text, чтобы динамически задать метку меню.

void Execute (IMenuCommand command);

Вызывается по щелчку пункта меню, если оно отображается и включено.

 

Доступ к модели в коде

Включение следующего объявления в класс команды меню

[Import] public IDiagramContext DiagramContext { get; set; }

...

Объявление IDiagramContext позволяет создавать код в методах, осуществляющих доступ к схеме, текущему выделению и модели.

IDiagram diagram = this.DiagramContext.CurrentDiagram;
foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>())
{ IElement element = shape.Element; ... }
IModelStore modelStore = diagram.ModelStore;
IModel model = modelStore.Root;
foreach (IElement element in modelStore.AllInstances<IUseCase>()) {...}

Навигация по модели и обновление модели

Все элементы модели UML доступны через API-интерфейс. Из текущего выделения или из корня модели можно осуществлять доступ ко всем другим элементам. Дополнительные сведения см. в разделах Практическое руководство. Навигация по UML-модели и Программирование с UML API.

Сведения о работе со схемой последовательностей см. в разделе Практическое руководство. Редактирование схем последовательностей с помощью API UML.

Кроме того, API-интерфейс позволяет изменять свойства элементов, удалять существующие и создавать новые элементы и отношения.

По умолчанию каждое изменение, вносимое в метод Execute, выполняется отдельной транзакцией. Пользователь сможет отменять изменения по отдельности. При необходимости объединить изменения в одну транзакцию, можно воспользоваться объектом ILinkedUndoTransaction, как описано в разделе Практическое руководство. Связывание обновлений модели с использованием транзакций.

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

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

Однако следует помнить, что хранилище модели не потокобезопасно. Следует также использовать поток пользовательского интерфейса для выполнения обновлений, и, если это возможно, предотвращать внесение изменений пользователем во время выполнения фоновой операции. Пример см. в разделе Пошаговое руководство. Обновление модели UML из фонового потока.

Выполнение команды меню

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

Проверка команды меню

  1. Нажмите F5 или щелкните в меню Отладка пункт Начать отладку.

    Откроется экспериментальный экземпляр Visual Studio.

    Устранение неполадок. Если новый экземпляр Visual Studio не запускается.

    • Если имеется более одного проекта, убедитесь, что проект VSIX назначен запускаемым проектом решения.

    • В обозревателе решений щелкните правой кнопкой мыши запускаемый проект или единственный проект и выберите пункт "Свойства". В редакторе свойств проекта перейдите на вкладку Отладка. Проверьте, что строка в поле Запуск внешней программы является полным путем к Visual Studio; обычно она имеет следующий вид:

      C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe

  2. В экспериментальном экземпляре Visual Studio откройте или создайте проект моделирования и откройте или создайте схему моделирования. Используйте схему одного из типов, перечисленных в атрибутах вашего класса команды меню.

  3. Щелкните правой кнопкой мыши в любом месте схемы. Команда должна появиться в меню.

    Устранение неполадок. Если команда не появилась в меню, убедитесь в следующем:

    • проект команды меню указан в качестве компонента MEF в списке Содержимое в source.extensions.manifest в проекте VSIX;

    • параметры атрибутов Import и Export являются допустимыми;

    • метод QueryStatus не задает для полей command.Enabled и Visible значение false;

    • Тип используемой схемы модели (UML-схема классов, схема последовательностей и т. д.) перечислен в качестве одного из атрибутов класса команды меню — [ClassDesignerExtension], [SequenceDesignerExtension] и т. д.

Установка и удаление расширения

Расширение Visual Studio можно установить как на своем компьютере, так и на других.

Установка расширения

  1. Найдите на компьютере файл .vsix, который был создан проектом VSIX.

    1. В обозревателе решений щелкните проект VSIX правой кнопкой мыши и выберите Открыть папку в проводнике.

    2. Найдите файл bin\*\Ваш_проект.vsix

  2. Скопируйте файл .vsix на конечный компьютер, на котором необходимо установить расширение. Это может быть ваш компьютер или любой другой.

    На конечном компьютере должен быть установлен один из выпусков Visual Studio, заданный в source.extension.vsixmanifest.

  3. Дважды щелкните файл .vsix на конечном компьютере.

    Visual Studio Extension Installer откроет и установит расширение.

  4. Запустите или перезапустите Visual Studio.

Удаление расширения

  1. В меню Сервис выберите пункт Диспетчер расширений.

  2. Разверните Установленные расширения.

  3. Выберите расширение и щелкните Удалить.

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

%LocalAppData%\Local\Microsoft\VisualStudio\10.0\Extensions

Пример

В следующем примере показан код команды меню, позволяющий поменять местами имена двух элементов на схеме классов. Этот код необходимо создать в проекте расширений Visual Studio и установить, следуя инструкциям предыдущих разделов.

using System.Collections.Generic; // for IEnumerable
using System.ComponentModel.Composition;
  // for [Import], [Export]
using System.Linq; // for IEnumerable extensions
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
  // for IDiagramContext
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
  // for designer extension attributes
using Microsoft.VisualStudio.Modeling.Diagrams;
  // for ShapeElement
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
  // for IGestureExtension, ICommandExtension, ILinkedUndoContext
using Microsoft.VisualStudio.Uml.Classes;
  // for class diagrams, packages

/// <summary>
/// Extension to swap names of classes in a class diagram.
/// </summary>
namespace SwapClassNames
{
  // Declare the class as an MEF component:
  [Export(typeof(ICommandExtension))]
  [ClassDesignerExtension]
  // Add more ExportMetadata attributes to make
  // the command appear on diagrams of other types.
  public class NameSwapper : ICommandExtension
  {
  // MEF required interfaces:
  [Import]
  public IDiagramContext Context { get; set; }
  [Import]
  public ILinkedUndoContext LinkedUndoContext { get; set; }

  /// <summary>
  /// Swap the names of the currently selected elements.
  /// </summary>
  /// <param name="command"></param>
  public void Execute(IMenuCommand command)
  {
    // Get selected shapes that are IClassifiers -
    // IClasses, IInterfaces, IEnumerators.
    var selectedShapes = Context.CurrentDiagram
     .GetSelectedShapes<IClassifier>();
    if (selectedShapes.Count() < 2) return;

    // Get model elements displayed by shapes.
    IClassifier firstElement = selectedShapes.First().Element;
    IClassifier lastElement = selectedShapes.Last().Element;

    // Do the swap in a transaction so that user
    // cannot undo one change without the other.
    using (ILinkedUndoTransaction transaction =
    LinkedUndoContext.BeginTransaction("Swap names"))
    {
    string firstName = firstElement.Name;
    firstElement.Name = lastElement.Name;
    lastElement.Name = firstName;
    transaction.Commit();
    }
  }

  /// <summary>
  /// Called by Visual Studio to determine whether
  /// menu item should be visible and enabled.
  /// </summary>
  public void QueryStatus(IMenuCommand command)
  { 
    int selectedClassifiers = Context.CurrentDiagram
     .GetSelectedShapes<IClassifier>().Count();
    command.Visible = selectedClassifiers > 0;
    command.Enabled = selectedClassifiers == 2;
  }

  /// <summary>
  /// Name of the menu command.
  /// </summary>
  public string Text
  {
    get { return "Swap Names"; }
  }
  }

}

См. также

Основные понятия

Расширение моделей и схем UML

Практическое руководство. Определение ограничений проверки для моделей UML

Программирование с UML API

Другие ресурсы

Практическое руководство. Определение и установка расширения моделирования

Практическое руководство. Определение обработчика перетаскивания и двойного щелчка на схеме моделирования

Практическое руководство. Определение настраиваемого элемента панели элементов моделирования

Практическое руководство. Редактирование схем последовательностей с помощью API UML

Sample: Command to Align Shapes on a UML Diagram