Adición de comandos de Visual Studio

Un comando representado por la Command clase es una acción que un usuario puede iniciar, como cuando el usuario elige un elemento de menú, presiona un botón de barra de herramientas o escribe un método abreviado de teclado. Los comandos tienen un nombre para mostrar, un método de ejecución (ExecuteCommandAsync) que realiza la acción, un icono para mostrar en la barra de herramientas para identificar el comando y una información sobre herramientas para explicar el comando al usuario. Los comandos se pueden habilitar o deshabilitar en función de varias condiciones.

Los comandos del nuevo modelo de extensibilidad se ejecutan de forma asincrónica para que el usuario pueda seguir interactuando con el IDE mientras se ejecutan los comandos.

Trabajar con comandos

En esta introducción se describen estos escenarios principales para trabajar con comandos:

Crear un comando

La creación de un comando con el nuevo modelo de extensibilidad comienza con la extensión de la clase Commandbase , adornando la clase con el VisualStudioContribution atributo e implementando la CommandConfiguration propiedad .

[VisualStudioContribution]
public class MyCommand : Command
{
  /// <inheritdoc />
  public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%");
}

Clase CommandConfiguration

La CommandConfiguration clase tiene algunos parámetros con los que debe familiarizarse:

Parámetro Type Obligatorio Description
DisplayName String Nombre para mostrar predeterminado del comando. Rodea esta cadena con el carácter '%' para habilitar la localización de esta cadena. Consulte la sección Localización de metadatos.
ToolTipText Cadena No Texto que se va a mostrar como la información sobre herramientas cuando el comando se mantiene o se centra. Rodea esta cadena con el carácter '%' para habilitar la localización de esta cadena. Consulte la sección Localización de metadatos.
Marcas CommandFlags No Marca para establecer propiedades adicionales en el comando . Algunas opciones incluyen CanToggle y CanSelect. Consulte en Marcas de comandos.
Colocaciones CommandPlacement[] No Especifica los grupos existentes en Visual Studio a los que se va a asociar el comando. Consulte En Colocar un comando en el IDE. Incluso sin ubicación, el comando seguirá estando disponible a través de la característica Búsqueda de Visual Studio. Los comandos también se pueden colocar en menús, barras de herramientas y grupos definidos en la extensión.
Icon CommandIconConfiguration No Los comandos se pueden mostrar en la interfaz de usuario como solo un icono, un icono con texto o simplemente texto. Esta propiedad configura qué debe ser ese icono, si existe, y cómo se debe mostrar.
Accesos directos CommandShortcutConfiguration[] No Define el conjunto de combinaciones de teclas que se pueden usar para ejecutar el comando. Los accesos directos se pueden limitar a que solo se apliquen a contextos ide específicos. Consulte en Accesos directos.
ClientContexts[] Cadena No Contextos de cliente solicitados por el comando . De forma predeterminada, se devuelven los contextos shell y Editor. Un contexto de cliente es una instantánea de estados de IDE específicos en el momento en que se ejecutó originalmente un comando. Dado que estos comandos se ejecutan de forma asincrónica, este estado podría cambiar entre el momento en que el usuario ejecutó el comando y el controlador de comandos en ejecución. Consulte en Contextos de cliente.

Ejemplo

Command También necesita un constructor que tome el objeto (que permite la VisualStudioExtensibility comunicación con el IDE) y un método ExecuteCommandAsyncde ejecución . En el ejemplo siguiente se proporciona una implementación mínima de un comando genérico que no hace nada:

[VisualStudioContribution]
public class MyCommand : Command
{
    /// <inheritdoc />
    public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%");

    public MyCommand(VisualStudioExtensibility extensibility)
        : base(extensibility)
    {
    }

    public override Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

Colocar un comando en el IDE

Hay un conjunto de lugares bien definidos en Visual Studio donde se pueden colocar los comandos. Estas ubicaciones se definen mediante la propiedad KnownPlacements de la clase CommandPlacement. El conjunto actual de KnownPlacements es:

  • ToolsMenu - El comando se colocará en un grupo bajo el menú de nivel superior "Herramientas" en Visual Studio.
  • ViewOtherWindowsMenu - El comando se colocará en un grupo bajo el menú "Ver" de nivel superior:> "Otras ventanas" en Visual Studio.
  • ExtensionsMenu - El comando se colocará en un grupo bajo el menú de nivel superior "Extensiones" en Visual Studio.

Los comandos también se pueden colocar mediante el CommandPlacement.VsctParent método especificando y GuidId del grupo definido a través de VSCT.

Los comandos primarios en el mismo grupo se ordenan en función de la propiedad de Priority su ubicación, en relación con otros comandos o menús con la misma ubicación. El valor predeterminado Priority de es CommandPlacement0 y se puede modificar llamando al CommandPlacement.WithPriority método y pasando el valor deseado Priority .

public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
    // The command will be parented to a group inside of the "Tools" top level menu,
    // a group inside of the "Extensions" top level menu, and the "About" group inside of the "Help" top level menu
    Placements = new CommandPlacement[]
    {
        CommandPlacement.KnownPlacements.ToolsMenu,
        CommandPlacement.KnownPlacements.ExtensionsMenu.WithPriority(0x0100),
        CommandPlacement.VsctParent(new Guid("{d309f791-903f-11d0-9efc-00a0c911004f}"), id: 0x016B, priority: 0x0801),
    },
};

Agregar un icono a un comando

Los comandos admiten la adición de iconos a su elemento de menú, ya sea además de o en lugar del nombre para mostrar del comando. Para agregar un icono al comando, establezca la Icon propiedad en el comando de CommandConfiguration.

CommandIconConfiguration

CommandIconConfiguration tiene dos parámetros:

Parámetro Type Obligatorio Descripción
IconName ImageMoniker Puede usar un moniker personalizado para una imagen que agregó después de la sección Agregar imágenes personalizadas o hacer referencia a un ImageMoniker de Visual Studio comoImageMonikers.KnownValues.AddItem
Icono Configuración Icono Configuración Configura cómo se mostrará el comando. Por ejemplo IconSettings.IconAndText , muestra el icono junto con el nombre para mostrar del comando, mientras que IconSettings.IconOnly solo mostrará el icono del comando y no su DisplayName si está primario en una barra de herramientas.

Ejemplo de ImageMoniker.KnownValues

public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
    Icon = new CommandIconConfiguration(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText),
};

Usar una imagen personalizada para el icono de comando

Puede agregar imágenes personalizadas, a las que puede hacer referencia con monikers personalizados siguiendo estos pasos:

  1. Cambie el nombre de los archivos de origen de la imagen para seguir el %Custom Moniker%.* patrón (por ejemplo, MyImage.1.png). Todos los archivos con el mismo moniker se usarán como orígenes de respaldo para el mismo moniker personalizado. Se usará un origen diferente en función del tamaño del icono solicitado.
    • Por ejemplo, MyImage.16.16.png (a 16*16 png), MyImage.20.20.png (a 20*20 png) y MyImage.xaml se consideran fuentes para MyImage.
    • Cuando el tamaño del icono solicitado es 16*16, se usará MyImage.16.16.png, cuando el tamaño solicitado sea 20*20, se usará MyImage.20.20.png, en todos los demás casos, se usará MyImage.xaml.
  2. Coloque todos los archivos de origen de la imagen en Images la carpeta .
    • La carpeta predeterminada de recursos de imagen es Images, pero también puede personalizarla agregando <ImageAssetsPath>%YourFolder%</ImageAssetsPath>

Ejemplo de ImageMoniker.Custom

public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
    Icon = new CommandIconConfiguration(ImageMoniker.Custom("MyImage"), IconSettings.IconAndText),
};

Accesos directos

Los comandos se pueden configurar para ejecutarse cuando se usa una combinación de teclas específica. Un método abreviado consta de uno o dos acordes, donde cada acorde consta de y ModifierKey uno Key. Los valores posibles para ModifierKey son LeftAlt, Shift, Control, ControlShift, ControlShiftLeftAlty None, donde None solo es válido cuando se usa en el segundo acorde de un acceso directo. No es necesario usar lo mismo ModifierKey para ambos acordes en un acceso directo. El Key usado en un acorde puede ser casi cualquier otra tecla de teclado.

Muchos métodos abreviados de teclado ya se usan en Visual Studio. No debe asignar el mismo acceso directo a más de un comando porque los enlaces duplicados son difíciles de detectar y también pueden provocar resultados imprevisibles. Por lo tanto, es una buena idea comprobar la disponibilidad de un acceso directo antes de asignarlo.

Restricción de activación de acceso directo

Se puede incluir una restricción de activación en la configuración para que el acceso directo esté disponible en distintos contextos. Estas restricciones de activación se definen en forma de Guidy normalmente se relacionan con un editor. Cuando se proporciona un acceso directo a una restricción de activación, solo estará disponible en ese contexto específico. Por ejemplo, use Guid "{5EFC7975-14BC-11CF-9B2B-00AA00573819}" para que el acceso directo esté disponible en el editor de Visual Studio. En este caso, el acceso directo solo estaría disponible cuando se centra el editor de Visual Studio.

Ejemplo de acceso directo

public override CommandConfiguration CommandConfiguration => new("%MyCommand.DisplayName%")
{
    Shortcuts = new CommandShortcutConfiguration[]
    {
        new(ModifierKey.LeftAlt, Key.M),
        new(ModifierKey.ControlShift, Key.Y, ModifierKey.ControlShift, Key.B),
    },
};

Configuración de un comando

Puede configurar la visibilidad y el estado habilitado o deshabilitado de un comando y establecer metadatos adicionales mediante marcas.

Visibilidad

La visibilidad de un comando se puede controlar estableciendo la VisibleWhen propiedad en el comando de CommandConfiguration.

El atributo admite la especificación de una condición a través de una serie de parámetros individuales que especifican la condición y todas sus entradas y lógicas. Para especificar la condición, especifique una expresión en un parámetro, defina un conjunto de términos (cadenas) usados en la expresión en otro parámetro y qué valores deben reemplazarse esos términos tras la evaluación en un tercer parámetro. La combinación de la expresión, los términos y los valores se denomina restricción de activación basada en reglas y se describe completamente en Restricciones de activación basadas en reglas.

Si se omite esta propiedad de la configuración, el valor predeterminado es que el comando siempre sea visible.

Ejemplo de visibilidad

public override CommandConfiguration CommandConfiguration => new("My command")
{
    VisibleWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveSelectionFileName, @"\.(jpg|jpeg|txt)$"),
};

Estado habilitado o deshabilitado

El estado habilitado o deshabilitado de un comando se puede controlar estableciendo la propiedad en el EnabledWhen comando.CommandConfiguration

Este tipo de configuración se denomina restricción de activación basada en reglas y se describe completamente en Uso de restricciones de activación basadas en reglas.

Si se omite esta configuración del comando, el valor predeterminado es que el comando siempre esté habilitado. También puede deshabilitar automáticamente el comando si se está ejecutando actualmente estableciendo this.DisableDuringExecution = true; en el constructor de la clase de comandos. Al establecer esta propiedad, se invalida el estado habilitado o deshabilitado definido por la EnabledWhen configuración mientras se ejecuta el comando.

Ejemplo de estado habilitado/deshabilitado

public override CommandConfiguration CommandConfiguration => new("My command")
{
    EnabledWhen = ActivationConstraint.ClientContext(ClientContextKey.Shell.ActiveSelectionFileName, @"\.(jpg|jpeg|txt)$"),
};

Para obtener más información sobre los valores de término válidos, consulte Restricciones de activación basadas en reglas.

Marcas de comandos

Las marcas de comandos ayudan a definir propiedades adicionales en los comandos que se usan en tiempo de ejecución para definir comportamientos especiales que el comando puede tener. Las marcas que se admiten actualmente son:

  • CanToggle - Indica que la IsChecked propiedad del comando puede cambiar para que los lectores de pantalla puedan anunciar el comando correctamente. Funcionalmente, garantiza que la propiedad IsTogglePatternAvailable de automatización devuelva true para el elemento de la interfaz de usuario.
  • CanSelect - Indica que la IsChecked propiedad del comando puede cambiar para que los lectores de pantalla puedan anunciar el comando correctamente. Funcionalmente, garantiza que la propiedad IsSelectionPatternAvailable de automatización devuelva true para el elemento de la interfaz de usuario.

Cambiar el nombre para mostrar de un comando

Aunque el nombre para mostrar de un comando se establece inicialmente en CommandConfiguration (vea Crear un comando), se puede cambiar en tiempo de ejecución estableciendo la propiedad en el DisplayName comando. La ToolTipText propiedad se puede actualizar de forma similar.

Ejemplo de cambio de DisplayName

[VisualStudioContribution]
public class MyCommand : Command
{
    /// <inheritdoc />
    public override CommandConfiguration CommandConfiguration => new("Initial Display Name");

    public MyCommand(VisualStudioExtensibility extensibility)
     : base(extensibility)
    {
    }

    public override Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
    {
        // Update the command's Display Name
        this.DisplayName = "Updated Display Name";
        return Task.CompletedTask;
    }
}

Pasos siguientes