Cómo: Agregar un comando a un menú contextual

Puede agregar comandos de menú al lenguaje (DSL) específico de modo que los usuarios puedan realizar tareas específicas de ADSL.Los comandos aparecen en el menú de contexto (acceso directo) cuando haga clic con el botón secundario de los usuarios en el diagrama.Puede definir un comando de modo que sólo aparece en el menú en determinadas circunstancias.Por ejemplo, puede hacer que el comando visible sólo cuando el usuario hace clic en determinados tipos de elemento, o elementos en estados concretas.

En resumen, los pasos se realizan en el proyecto de DslPackage, como sigue:

  1. declare el comando en Commands.vsct

  2. Actualice el número de versión del paquete en Package.tt.Debe hacer esto siempre que se cambia Commands.vsct

  3. Escribir métodos en la clase de CommandSet para crear el comando visible y para definir lo que desea que el comando de hacer.

Para obtener ejemplos, vea Visualización y modelado del sitio Web de SDK.

[!NOTA]

También puede modificar el comportamiento de algunos comandos existentes como cut, pegar, seleccione Todo, y impresión reemplazando los métodos en CommandSet.cs.Para obtener más información, vea Cómo: Modificar comandos de menú estándar en lenguajes específicos de dominio.

Definir un comando mediante MEF

El marco de extensión administrada (MEF) proporciona un método alternativo de definir comandos en el menú del diagrama.El propósito principal es habilitar ADSL que se extenderá por usted o por terceros.Los usuarios pueden elegir instalarlo solo DSL, o pueden instalar ADSL y extensiones.Sin embargo, MEF también reduce el trabajo de definir comandos de menú contextual, después del trabajo inicial de habilitar MEF en ADSL.

Utilice el método de este tema si:

  1. Desea definir comandos en menús distinto del menú contextual del botón secundario.

  2. Desea definir agrupaciones específicas de comandos del menú.

  3. No desea permitir que otros para extender ADSL con sus propios comandos.

  4. Sólo desea definir un comando.

Si no, considere el uso del método MEF para definir comandos.Para obtener más información, vea Ampliar DSL mediante MEF.

declare el comando en Commands.Vsct

Se declaran los comandos de menú en DslPackage \Commands .vsct.Estas definiciones especifican las etiquetas de los elementos de menú y dónde aparecen en los menús.

El archivo que se edición, Commands.vsct, importar definiciones de varios archivos .h, que se encuentran en el directorio Ruta de instalación de Visual Studio SDK\VisualStudioIntegration\Common\Inc.También incluye GeneratedVsct.vsct, que se genera a partir de la definición del ADSL.

Para obtener más información sobre los archivos de .vsct, vea Tabla de comandos de Visual Studio (. archivos de Vsct).

para agregar el comando

  1. En Explorador de soluciones, bajo el proyecto de DslPackage , abra Commands.vsct.

  2. En el elemento de Commands , defina uno o varios botones y un grupo.Un botón es un elemento del menú.Un grupo es una sección del menú.para definir estos elementos, agregue los elementos siguientes:

    <!-- Define a group - a section in the menu -->
    <Groups>
      <Group guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup" priority="0x0100">
        <!-- These symbols are defined in GeneratedVSCT.vsct -->
        <Parent guid="guidCmdSet" id="menuidContext" />
      </Group>
    </Groups>
    <!-- Define a button - a menu item - inside the Group -->
    <Buttons>
      <Button guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        priority="0x0100" type="Button">
        <Parent guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup"/>
        <!-- If you do not want to place the command in your own Group, 
             use Parent guid="guidCmdSet" id="grpidContextMain".
             These symbols are defined in GeneratedVSCT.vsct -->
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <ButtonText>My Context Menu Command</ButtonText>
        </Strings>
      </Button>
    </Buttons>
    

    [!NOTA]

    Cada botón o grupo identifica un GUID y un identificador enteroPuede crear varios grupos y botones con el mismo GUID.Sin embargo, deben tener diferentes id.Los nombres del GUID y los nombres de identificador se convierten en GUID real y los id. numéricos en el nodo de <Símbolos> .

  3. Agregue una restricción de visibilidad para el comando cargarlo solo en el contexto del lenguaje específico.Para obtener más información, vea VisibilityConstraints (Elemento).

    Para ello, agregue los elementos siguientes en el elemento de CommandTable después del elemento de Commands .

    <VisibilityConstraints>
      <!-- Ensures the command is only loaded for this DSL -->
      <VisibilityItem guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        context="guidEditor"/>
    </VisibilityConstraints>
    
  4. Defina los nombres que utilizó para los GUID y los id.Para ello, agregue un elemento de Symbols en el elemento de CommandTable después del elemento de Commands .

    <Symbols>
      <!-- Substitute a unique GUID for the placeholder: -->
      <GuidSymbol name="guidCustomMenuCmdSet"
        value="{00000000-0000-0000-0000-000000000000}" >
        <IDSymbol name="grpidMyMenuGroup" value="0x01001"/>
        <IDSymbol name="cmdidMyContextMenuCommand" value="0x00001"/>
      </GuidSymbol>
    </Symbols>
    
  5. Reemplace {000...000} con un GUID que identifica los grupos y los elementos de menú.Para obtener un nuevo GUID, utilice la herramienta de Crear GUID en el menú de Herramientas .

    [!NOTA]

    Si agrega más grupos o elementos de menú, puede utilizar el mismo GUID.Sin embargo, debe utilizar los nuevos valores para IDSymbols.

  6. En el código que haya copiado de este procedimiento, reemplace cada aparición de las cadenas siguientes con dispone de cadenas:

    • grpidMyMenuGroup

    • cmdidMyContextMenuCommand

    • guidCustomMenuCmdSet

    • El comando de menú contextual

Actualice la versión del paquete en Package.tt

Siempre que agregue o cambiar un comando, actualice el parámetro de version de ProvideMenuResourceAttribute que se aplica a la clase de paquete antes de que se libere la nueva versión de lenguaje específico.

Dado que la clase de paquete está definido en un archivo generado, actualice el atributo en el archivo de plantilla de texto que genera el archivo de Package.cs.

para actualizar el archivo de Package.tt

  1. En Explorador de soluciones, en el proyecto de DslPackage , en la carpeta de GeneratedCode , abra el archivo de Package.tt.

  2. Busque el atributo de ProvideMenuResource .

  3. Aumente el parámetro de version del atributo, que es el segundo parámetro.Si lo desea, puede escribir el nombre de parámetro explícitamente para recordarle su propósito.Por ejemplo:

    [VSShell::ProvideMenuResource("1000.ctmenu", version: 2 )]

Define el comportamiento del comando

DSL ya tiene algunos comandos que se implementa en una clase parcial que se declara en DslPackage \GeneratedCode\CommandSet .cs.Para agregar nuevos comandos, debe extender esta clase creando un nuevo archivo que contiene una declaración parcial de la misma clase.El nombre de la clase es normalmente <TheDslName> CommandSet.Es útil comenzar comprobando el nombre de la clase e inspeccionar su contenido.

La clase determinada de comando es derivada de CommandSet.

para extender la clase de CommandSet

  1. En el explorador de soluciones, en el proyecto de DslPackage, abra la carpeta GeneratedCode y después busca en CommandSet.tt y abra el archivo generado CommandSet.cs.Observe el espacio de nombres y el nombre de la primera clase definido allí.Por ejemplo, podría aparecer:

    namespace Company.Language1

    { ... internal partial class Language1CommandSet : ...

  2. En DslPackage, cree una carpeta que se denomina código personalizado.En esta carpeta, cree un nuevo archivo de clase denominado CommandSet.cs.

  3. En el nuevo archivo, escriba una declaración parcial que tiene el mismo espacio de nombres y nombre que la clase parcial generada.Por ejemplo:

    namespace Company.Language1 /* Make sure this is correct */

    { internal partial class Language1CommandSet { ...

Observe si utilizó la plantilla de clase para crear el nuevo archivo, debe corregir el espacio de nombres y el nombre de clase.

Dd820681.collapse_all(es-es,VS.110).gifExtiende la clase determinada de comando

El código del comando necesitará normalmente importar los espacios de nombres siguientes:

using System;
using System.Collections.Generic;
using System.ComponentModel.Design; 
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Shell;

Ajuste el espacio de nombres y el nombre de clase para coincidir con los del CommandSet.cs generado:

namespace Company.Language1 /* Make sure this is correct */
{
  // Same class as the generated class.
  internal partial class Language1CommandSet 
  {

Debe definir dos métodos, uno para determinar cuando el comando estará visible en el menú contextual, y el otro para ejecutar el comando.estos métodos no son reemplazan; en su lugar, se registra en una lista de comandos.

Dd820681.collapse_all(es-es,VS.110).gifDefine cuándo el comando será visible

Para cada comando, defina un método de OnStatus... que determina si el comando aparecerá en el menú, y si se habilitará o greyed out.Establezca las propiedades de Visible y de Enabled de MenuCommand, como se muestra en el ejemplo siguiente.Se llama a este método para construir el menú contextual cada vez que el usuario hace clic con el botón secundario en el diagrama, por lo que debe funcionar rápidamente.

En este ejemplo, el comando sólo está visible cuando el usuario tiene seleccionado un tipo determinado de forma, y sólo está habilitada cuando al menos uno de los elementos seleccionados está en un estado determinado.El ejemplo se basa en la plantilla ADSL de diagrama de clases, y ClassShape y ModelClass son tipos que se definen en ADSL:

private void OnStatusMyContextMenuCommand(object sender, EventArgs e)
{
  MenuCommand command = sender as MenuCommand;
  command.Visible = command.Enabled = false;
  foreach (object selectedObject in this.CurrentSelection)
  {
    ClassShape shape = selectedObject as ClassShape;
    if (shape != null)
    {
      // Visibility depends on what is selected.
      command.Visible = true;
      ModelClass element = shape.ModelElement as ModelClass;
      // Enabled depends on state of selection.
      if (element != null && element.Comments.Count == 0)
      {
        command.Enabled = true;
        return; // seen enough
} } } }

Fragmentos siguientes suelen ser útiles en los métodos de OnStatus:

  • this.CurrentSelection.La forma en la que el usuario hizo clic derecho siempre se incluye en esta lista.Si el usuario hace clic en una parte en blanco del diagrama, el diagrama es el único miembro de la lista.

  • this.IsDiagramSelected() - true si el usuario hizo clic en una parte en blanco del diagrama.

  • this.IsCurrentDiagramEmpty()

  • this.IsSingleSelection() - el usuario no seleccionar varios objetos

  • this.SingleSelection - la forma o el diagrama que hizo clic el usuario derecho

  • shape.ModelElement as MyLanguageElement - el elemento modelo representado por una forma.

Como norma general, cree la propiedad de Visible depende de lo que está seleccionado, y hace que la propiedad de Enabled depende del estado de los elementos seleccionados.

Un método de OnStatus no debe cambiar el estado del almacén.

Dd820681.collapse_all(es-es,VS.110).gifDefina qué hace el comando

Para cada comando, defina un método de OnMenu... que realice la acción necesaria cuando el usuario hace clic en el comando de menú.

Si realiza cambios en los elementos de modelo, debe hacerlo dentro de una transacción.Para obtener más información, vea Cómo: Modificar comandos de menú estándar en lenguajes específicos de dominio.

En este ejemplo, ClassShape, ModelClass, y Comment son tipos que se definen en DSL, que es derivado de plantilla ADSL de diagrama de clases.

private void OnMenuMyContextMenuCommand(object sender, EventArgs e)
{
  MenuCommand command = sender as MenuCommand;
  Store store = this.CurrentDocData.Store;
  // Changes to elements and shapes must be performed in a Transaction.
  using (Transaction transaction =
       store.TransactionManager.BeginTransaction("My command"))
  {
    foreach (object selectedObject in this.CurrentSelection)
    {
      // ClassShape is defined in my DSL.
      ClassShape shape = selectedObject as ClassShape;
      if (shape != null)
      {
        // ModelClass is defined in my DSL.
        ModelClass element = shape.ModelElement as ModelClass;
        if (element != null)
        {
          // Do required action here - for example:

          // Create a new element. Comment is defined in my DSL.
          Comment newComment = new Comment(element.Partition);
          // Every element must be the target of an embedding link.
          element.ModelRoot.Comments.Add(newComment);
          // Set properties of new element.
          newComment.Text = "This is a comment";
          // Create a reference link to existing object.
          element.Comments.Add(newComment);
        }
      }
    }
    transaction.Commit(); // Don't forget this!
  }
}

Para obtener más información sobre cómo navegar de objeto en el objeto en el modelo, y cómo establecer objetos y las relaciones, vea Cómo: Modificar comandos de menú estándar en lenguajes específicos de dominio.

Dd820681.collapse_all(es-es,VS.110).gifregistre el comando

Repita en C# las declaraciones del GUID y los valores ID que creó en la sección de Símbolos de CommandSet.vsct:

    private Guid guidCustomMenuCmdSet = 
        new Guid("00000000-0000-0000-0000-000000000000");
    private const int grpidMyMenuGroup = 0x01001;
    private const int cmdidMyContextMenuCommand = 1;

Use el mismo valor de GUID que insertó en Commands.vsct.

[!NOTA]

Si cambia la sección símbolos de archivo de VSCT, también debe cambiar estas declaraciones que coincida.También debe aumentar el número de versión en Package.tt

Registre los comandos de menú como parte de este conjunto de comando.GetMenuCommands() se llama una vez cuando se inicializa el diagrama:

protected override IList<MenuCommand> GetMenuCommands()
{
  // Get the list of generated commands.
  IList<MenuCommand> commands = base.GetMenuCommands();
  // Add a custom command:
  DynamicStatusMenuCommand myContextMenuCommand =
    new DynamicStatusMenuCommand(
      new EventHandler(OnStatusMyContextMenuCommand),
      new EventHandler(OnMenuMyContextMenuCommand),
      new CommandID(guidCustomMenuCmdSet, cmdidMyContextMenuCommand));
  commands.Add(myContextMenuCommand);
  // Add more commands here.
  return commands;
} 

pruebe el comando

Compile y ejecute ADSL en una instancia experimental de Visual Studio.El comando debe aparecer en el menú contextual en situaciones que ha especificado.

Para ejecutar el comando

  1. En la barra de herramientas de Explorador de soluciones , haga clic en Transformar todas las plantillas.

  2. Presione F5 para recompilar la solución y, inicie la depuración del lenguaje específico en la compilación experimental.

  3. En la compilación experimental, abra un diagrama de ejemplo.

  4. Diversos elementos del botón secundario en el diagrama para comprobar que permiten o se deshabilitado el comando correctamente, y muestre correctamente o oculto, dependiendo del elemento seleccionado.

Solución de problemas

El comando no aparece en el menú:

  • El comando solo aparecerá en instancias de depuración de Visual Studio, hasta que instale el paquete ADSL.Para obtener más información, vea Implementar soluciones de lenguajes específicos de dominio.

  • Asegúrese de que el ejemplo experimental tiene la extensión de nombre de archivo correcta para este ADSL.para comprobar la extensión de nombre de archivo, abra DslDefinition.dsl en la instancia principal de Visual Studio.A continuación en el Explorador ADSL, haga clic con el botón secundario en el editor, y haga clic en propiedades.en la ventana Propiedades, examine la propiedad de FileExtension.

  • ¿Hizo se aumente el número de versión del paquete?

  • Establezca un punto de interrupción al principio del método de OnStatus.Debe interrumpir al hacer clic con el botón secundario en cualquier parte del diagrama.

    el método de OnStatus no se denomina:

    • Asegúrese de que el GUID y los id. en el código de CommandSet los de la sección de Símbolos de Commands.vsct.

    • En Commands.vsct, asegúrese de que el GUID y el identificador en cada nodo primario identifican el grupo primario correcto.

    • En un símbolo del sistema de Visual Studio, escriba devenv /rootsuffix exp /setup.A continuación reinicie la instancia de depuración de Visual Studio.

  • Recorra el método de OnStatus para comprobar que el comando. visible y comando. Enabled se establecen en true.

El texto de menú incorrecto aparece, o el comando aparecerá en un lugar incorrecto:

  • Asegúrese de que la combinación de GUID y de identificador es única a este comando.

  • Asegúrese de que ha desinstalado versiones anteriores del paquete.

Vea también

Conceptos

Cómo: Modificar comandos de menú estándar en lenguajes específicos de dominio

Otros recursos

Escribir código para personalizar lenguajes específicos de dominio

Código de ejemplo: esquemas circulares