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

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

Требования

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

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

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

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

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

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

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

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

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

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

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

Альтернативная процедура:

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

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

    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.11.0

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

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

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.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]
    
      // All menu commands must export ICommandExtension:
      [Export (typeof(ICommandExtension))]
      // CHANGE class name – determines order of appearance on menu:
      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. В Обозреватель решений, в контекстном меню решения выберите Добавить, Создать проект.

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

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

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

    1. На вкладке Метаданные задайте имя VSIX.

    2. На вкладке Цели установки задайте Visual Studio Ultimate и Premium в качестве целевых объектов.

    3. На вкладке Активы выберите Создать и в диалоговом окне установите:

      Тип = Компонент MEF

      Источник = Проект в текущем решении

      Проект = Проект библиотеки классов

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

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

string Text { get; }

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

void QueryStatus(IMenuCommand command);

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

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

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

Задайте

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

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

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

void Execute (IMenuCommand command);

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

 

Ee329481.collapse_all(ru-ru,VS.110).gifДоступ к модели в коде

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

[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>()) {...}

Ee329481.collapse_all(ru-ru,VS.110).gifНавигация по модели и обновление модели

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

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

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

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

Ee329481.collapse_all(ru-ru,VS.110).gifИспользование потока пользовательского интерфейса для обновлений

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

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

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

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

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

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

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

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

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

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

      C:\Program Files\Microsoft Visual Studio 11.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 выберите Открыть папку в проводнике Windows.

    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\11.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

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

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

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

Пример: команда для выравнивания фигур на диаграмме UML