Uso de comandos en aplicaciones de Windows con StandardUICommand, XamlUICommand e ICommandCommanding in Windows apps using StandardUICommand, XamlUICommand, and ICommand

En este tema, se describe el uso de comandos en aplicaciones de Windows.In this topic, we describe commanding in Windows applications. Concretamente, vamos a explicar cómo usar las clases XamlUICommand y StandardUICommand (junto con la interfaz ICommand) para compartir y administrar comandos entre diversos tipos de controles, independientemente del tipo de dispositivo y de la entrada que se va a usar.Specifically, we discuss how you can use the XamlUICommand and StandardUICommand classes (along with the ICommand interface) to share and manage commands across various control types, regardless of the device and input type being used.

Un diagrama que representa un uso común para un comando compartido; expone varias superficies de interfaz de usuario con un comando "favorito"

Compartir comandos entre varios controles, independientemente del dispositivo y el tipo de entradaShare commands across various controls, regardless of device and input type

API importantesImportant APIs

IntroducciónOverview

Los comandos se pueden invocar directamente mediante interacciones de la interfaz de usuario, como hacer clic en un botón o seleccionar un elemento de un menú contextual.Commands can be invoked directly through UI interactions like clicking a button or selecting an item from a context menu. También se pueden invocar indirectamente a través de un dispositivo de entrada como teclas de aceleración, gestos, reconocimiento de voz o una herramienta de automatización y accesibilidad.They can also be invoked indirectly through an input device such as a keyboard accelerator, gesture, speech recognition, or an automation/accessibility tool. Una vez invocado, el comando se puede controlar mediante un control (navegación de texto en un control de edición), una ventana (navegación hacia atrás) o la aplicación (salir).Once invoked, the command can then be handled by a control (text navigation in an edit control), a window (back navigation), or the application (exit).

Los comandos pueden funcionar en un contexto específico dentro de la aplicación, por ejemplo, eliminar texto o deshacer una acción, o pueden ser independientes del contexto, por ejemplo, silenciar el audio o ajustar el brillo.Commands can operate on a specific context within your app, such as deleting text or undoing an action, or they can be context-free, such as muting audio or adjusting brightness.

En la siguiente imagen se muestran dos interfaces de comandos (CommandBar y una interfaz contextual flotante CommandBarFlyout) que comparten algunos comandos.The following image shows two command interfaces (a CommandBar and a floating contextual CommandBarFlyout) that share some of the same commands.

Barra de comandos expandidaExpanded Command bar
Barra de comandosCommand bar

Menú contextual de la galería de Fotos de MicrosoftContext menu in the Microsoft Photos gallery
Menú contextual de la galería de Fotos de MicrosoftContext menu in the Microsoft Photos gallery

Interacciones de comandoCommand interactions

Debido a la variedad de dispositivos, tipos de entrada y superficies de interfaz de usuario, que puede afectar a cómo se invoca un comando, se recomienda exponer los comandos en tantas superficies de comandos como sea posible.Due to the variety of devices, input types, and UI surfaces that can affect how a command is invoked, we recommend exposing your commands through as many commanding surfaces as possible. Estas pueden incluir una combinación de Swipe, MenuBar, CommandBar, CommandBarFlyout y el menú contextual tradicional.These can include a combination of Swipe, MenuBar, CommandBar, CommandBarFlyout, and traditional context menu.

Para los comandos críticos, usa aceleradores específicos de la entrada.For critical commands, use input-specific accelerators. Los aceleradores de entrada permiten a un usuario realizar acciones más rápidamente en función del dispositivo de entrada que están usando.Input accelerators let a user perform actions more quickly depending on the input device they're using.

Estos son algunos aceleradores de entrada comunes para varios tipos de entrada:Here are some common input accelerators for various input types:

  • Puntero: botones para mantener el puntero con el mouse y lápiz.Pointer - Mouse & Pen hover buttons
  • Teclado: métodos abreviados (teclas de acceso y teclas de aceleración).Keyboard - Shortcuts (access keys and accelerator keys)
  • Táctil: deslizar el dedo.Touch - Swipe
  • Táctil: arrastrar actualizar los datos.Touch - Pull to refresh data

Debes tener en cuenta las experiencias de usuario y el tipo de entrada para que la funcionalidad de tu aplicación sea universalmente accesible.You must consider the input type and user experiences to make your application's functionality universally accessible. Por ejemplo, las colecciones (especialmente las que el usuario puede editar) normalmente incluyen una serie de comandos específicos que se comportan de forma bastante diferente según el dispositivo de entrada.For example, collections (especially user editable ones) typically include a variety of specific commands that are performed quite differently depending on the input device.

En esta tabla se muestran algunos comandos de colección típicos y las formas de exponerlos.The following table shows some typical collection commands and ways to expose those commands.

ComandoCommand Independiente de la entradaInput-agnostic Acelerador de mouseMouse accelerator Teclas de aceleraciónKeyboard accelerator Acelerador de entrada táctilTouch accelerator
Eliminar elementoDelete item Menú contextualContext menu Botón interactivoHover button Tecla SuprDEL key Deslizar el dedo para eliminarSwipe to delete
Marcar elementoFlag item Menú contextualContext menu Botón interactivoHover button Ctrl + Mayús + GCtrl+Shift+G Deslizar el dedo para marcarSwipe to flag
Actualizar datosRefresh data Menú contextualContext menu N/AN/A Tecla F5F5 key Extraer para actualizarPull to refresh
Marcar como favorito un elementoFavorite an item Menú contextualContext menu Botón interactivoHover button F, Ctrl+SF, Ctrl+S Deslizar el dedo para favoritoSwipe to favorite

Proporciona siempre un menú contextual Te recomendamos incluir todos los comandos contextuales pertinentes en un menú contextual tradicional o CommandBarFlyout, porque ambos son compatibles con todos los tipos de entrada.Always provide a context menu We recommend including all relevant contextual commands in a traditional context menu or CommandBarFlyout, as both are supported for all input types. Por ejemplo, si un comando se expone solo durante un evento de mantener el puntero, no puede utilizarse en un dispositivo solo táctil.For example, if a command is exposed only during a pointer hover event, it cannot be used on a touch-only device.

Comandos en aplicaciones de WindowsCommands in Windows applications

Hay varias maneras de compartir y administrar las experiencias del uso de comandos en una aplicación de Windows.There are a few ways you can share and manage commanding experiences in a Windows application. Puedes definir controladores de eventos para las interacciones estándar, como hacer clic, en el código subyacente (esto puede ser bastante ineficaz según la complejidad de la interfaz de usuario), puedes enlazar la escucha de eventos para las interacciones estándar a un controlador compartido, o puedes enlazar la propiedad Command del control a una implementación de ICommand que describa la lógica del comando.You can define event handlers for standard interactions, such as Click, in code-behind (this can be quite inefficient, depending on the complexity of your UI), you can bind event listener for standard interactions to a shared handler, or you can bind the control's Command property to an ICommand implementation that describes the command logic.

Para proporcionar experiencias de usuario completas y enriquecidas en distintas superficies de comandos, de forma eficaz y con una duplicación de código mínima, se recomienda usar las características de enlace de comandos descritas en este tema (para el control de eventos estándar, consulta cada uno de los temas de eventos).To provide rich and comprehensive user experiences across command surfaces efficiently and with minimal code duplication, we recommend using the command binding features described in this topic(for standard event handling, see the individual event topics).

Para enlazar un control a un recurso de comando compartido, puedes implementar interfaces ICommand o puedes crear el comando desde la clase base XamlUICommand o uno de los comandos de plataforma definidos por la clase derivada StandardUICommand.To bind a control to a shared command resource, you can implement the ICommand interfaces yourself, or you can build your command from either the XamlUICommand base class or one of the platform commands defined by the StandardUICommand derived class.

  • La interfaz ICommand (Windows.UI.Xaml.Input.ICommand o System.Windows.Input.ICommand) permite crear comandos reutilizables y totalmente personalizados en toda la aplicación.The ICommand interface (Windows.UI.Xaml.Input.ICommand or System.Windows.Input.ICommand) lets you create fully customized, reusable commands across your app.
  • XamlUICommand también ofrece esta funcionalidad, pero simplifica el desarrollo porque expone un conjunto de propiedades de comandos integradas tales como el comportamiento del comando, métodos abreviados de teclado (tecla de acceso y tecla de aceleración), icono, etiqueta y descripción.XamlUICommand also provides this capability but simplifies development by exposing a set of built-in command properties such as the command behavior, keyboard shortcuts (access key and accelerator key), icon, label, and description.
  • StandardUICommand simplifica aún más las cosas porque permite elegir en un conjunto de comandos de plataforma estándar con las propiedades predefinidas.StandardUICommand simplifies things further by letting you choose from a set of standard platform commands with predefined properties.

Importante

En las aplicaciones para UWP, los comandos son implementaciones de las interfaces Windows.UI.Xaml.Input.ICommand (C++) o System.Windows.Input.ICommand (C#), según el lenguaje elegido.In UWP applications, commands are implementations of either the Windows.UI.Xaml.Input.ICommand (C++) or the System.Windows.Input.ICommand (C#) interface, depending on your chosen language framework.

Experiencias con comandos con la clase StandardUICommandCommand experiences using the StandardUICommand class

Derivada de XamlUiCommand (que deriva de Windows.UI.Xaml.Input.ICommand para C++ o System.Windows.Input.ICommand para C#), la clase StandardUICommand expone un conjunto de comandos de plataforma estándar con propiedades predefinidas tales como icono, tecla de aceleración y descripción.Derived from XamlUiCommand (derived from Windows.UI.Xaml.Input.ICommand for C++ or System.Windows.Input.ICommand for C#), the StandardUICommand class exposes a set of standard platform commands with pre-defined properties such as icon, keyboard accelerator, and description.

StandardUICommand ofrece una manera rápida y coherente de definir comandos comunes, como Save o Delete.A StandardUICommand provides a quick and consistent way to define common commands such as Save or Delete. Lo único que debe hacer es proporcionar las funciones execute y canExecute.All you have to do is provide the execute and canExecute functions.

EjemploExample

Ejemplo de StandardUICommand

StandardUICommandSampleStandardUICommandSample

Descargar el código de este ejemplo.Download the code for this example
Ejemplo de comandos de UWP (StandardUICommand)UWP commanding sample (StandardUICommand)

En este ejemplo, se muestra cómo mejorar un control ListView básico con el comando para eliminar elementos que se implementa mediante la clase StandardUICommand, al tiempo que se optimiza la experiencia del usuario para diversos tipos de entrada mediante controles MenuBar o Swipe, botones en los que mantener el puntero y menú contextual.In this example, we show how to enhance a basic ListView with a Delete item command implemented through the StandardUICommand class, while optimizing the user experience for a variety of input types using a MenuBar, Swipe control, hover buttons, and context menu.

Nota

Este ejemplo requiere el paquete de NuGet Microsoft.UI.Xaml.Controls, que forma parte de la biblioteca de interfaz de usuario de Microsoft Windows.This sample requires the Microsoft.UI.Xaml.Controls NuGet package, a part of the Microsoft Windows UI Library.

Xaml:Xaml:

El ejemplo de interfaz de usuario incluye un control ListView con cinco elementos.The sample UI includes a ListView of five items. El comando StandardUICommand Delete está enlazado a MenuBarItem, SwipeItem, AppBarButton y un menú contextual.The Delete StandardUICommand is bound to a MenuBarItem, a SwipeItem, an AppBarButton, and ContextFlyout menu.

<Page
    x:Class="StandardUICommandSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:StandardUICommandSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:muxcontrols="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Page.Resources>
        <Style x:Key="HorizontalSwipe" 
               TargetType="ListViewItem" 
               BasedOn="{StaticResource ListViewItemRevealStyle}">
            <Setter Property="Height" Value="60"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
    </Page.Resources>

    <Grid Loaded="ControlExample_Loaded">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" 
                    Padding="10" 
                    BorderThickness="0,0,0,1" 
                    BorderBrush="LightBlue"
                    Background="AliceBlue">
            <TextBlock Style="{StaticResource HeaderTextBlockStyle}">
                StandardUICommand sample
            </TextBlock>
            <TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,10">
                This sample shows how to use the StandardUICommand class to 
                share a platform command and consistent user experiences 
                across various controls.
            </TextBlock>
            <TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,0">
                Specifically, we define a standard delete command and add it 
                to a variety of command surfaces, all of which share a common 
                icon, label, keyboard accelerator, and description.
            </TextBlock>
        </StackPanel>

        <muxcontrols:MenuBar Grid.Row="1" Padding="10">
            <muxcontrols:MenuBarItem Title="File">
            </muxcontrols:MenuBarItem>
            <muxcontrols:MenuBarItem Title="Edit">
                <MenuFlyoutItem x:Name="DeleteFlyoutItem"/>
            </muxcontrols:MenuBarItem>
            <muxcontrols:MenuBarItem Title="Help">
            </muxcontrols:MenuBarItem>
        </muxcontrols:MenuBar>

        <ListView x:Name="ListViewRight" Grid.Row="2" 
                  Loaded="ListView_Loaded" 
                  IsItemClickEnabled="True" 
                  SelectionMode="Single" 
                  SelectionChanged="ListView_SelectionChanged" 
                  ItemContainerStyle="{StaticResource HorizontalSwipe}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:ListItemData">
                    <UserControl PointerEntered="ListViewSwipeContainer_PointerEntered" 
                                 PointerExited="ListViewSwipeContainer_PointerExited">
                        <UserControl.ContextFlyout>
                            <MenuFlyout>
                                <MenuFlyoutItem 
                                    Command="{x:Bind Command}" 
                                    CommandParameter="{x:Bind Text}" />
                            </MenuFlyout>
                        </UserControl.ContextFlyout>
                        <Grid AutomationProperties.Name="{x:Bind Text}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="HoveringStates">
                                    <VisualState x:Name="HoverButtonsHidden" />
                                    <VisualState x:Name="HoverButtonsShown">
                                        <VisualState.Setters>
                                            <Setter Target="HoverButton.Visibility" 
                                                    Value="Visible" />
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <SwipeControl x:Name="ListViewSwipeContainer" >
                                <SwipeControl.RightItems>
                                    <SwipeItems Mode="Execute">
                                        <SwipeItem x:Name="DeleteSwipeItem" 
                                                   Background="Red" 
                                                   Command="{x:Bind Command}" 
                                                   CommandParameter="{x:Bind Text}"/>
                                    </SwipeItems>
                                </SwipeControl.RightItems>
                                <Grid VerticalAlignment="Center">
                                    <TextBlock Text="{x:Bind Text}" 
                                               Margin="10" 
                                               FontSize="18" 
                                               HorizontalAlignment="Left" 
                                               VerticalAlignment="Center"/>
                                    <AppBarButton x:Name="HoverButton" 
                                                  IsTabStop="False" 
                                                  HorizontalAlignment="Right" 
                                                  Visibility="Collapsed" 
                                                  Command="{x:Bind Command}" 
                                                  CommandParameter="{x:Bind Text}"/>
                                </Grid>
                            </SwipeControl>
                        </Grid>
                    </UserControl>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

Código subyacenteCode-behind

  1. En primer lugar, definimos una clase ListItemData que contiene una cadena de texto e ICommand para cada ListViewItem de nuestro control ListView.First, we define a ListItemData class that contains a text string and ICommand for each ListViewItem in our ListView.
public class ListItemData
{
    public String Text { get; set; }
    public ICommand Command { get; set; }
}
  1. En la clase MainPage, definimos una colección de objetos ListItemData para la plantilla de datos DataTemplate de la plantilla ListView ItemTemplate.In the MainPage class, we define a collection of ListItemData objects for the DataTemplate of the ListView ItemTemplate. Después la rellenamos con una colección inicial de cinco elementos (con texto y el comando StandardUICommand Delete asociado).We then populate it with an initial collection of five items (with text and associated StandardUICommand Delete).
/// <summary>
/// ListView item collection.
/// </summary>
ObservableCollection<ListItemData> collection = 
    new ObservableCollection<ListItemData>();

/// <summary>
/// Handler for the layout Grid control load event.
/// </summary>
/// <param name="sender">Source of the control loaded event</param>
/// <param name="e">Event args for the loaded event</param>
private void ControlExample_Loaded(object sender, RoutedEventArgs e)
{
    // Create the standard Delete command.
    var deleteCommand = new StandardUICommand(StandardUICommandKind.Delete);
    deleteCommand.ExecuteRequested += DeleteCommand_ExecuteRequested;

    DeleteFlyoutItem.Command = deleteCommand;

    for (var i = 0; i < 5; i++)
    {
        collection.Add(
            new ListItemData {
                Text = "List item " + i.ToString(),
                Command = deleteCommand });
    }
}

/// <summary>
/// Handler for the ListView control load event.
/// </summary>
/// <param name="sender">Source of the control loaded event</param>
/// <param name="e">Event args for the loaded event</param>
private void ListView_Loaded(object sender, RoutedEventArgs e)
{
    var listView = (ListView)sender;
    // Populate the ListView with the item collection.
    listView.ItemsSource = collection;
}
  1. A continuación, definimos el controlador ExecuteRequested de ICommand donde se implementa el comando de eliminación de elementos.Next, we define the ICommand ExecuteRequested handler where we implement the item delete command.
/// <summary>
/// Handler for the Delete command.
/// </summary>
/// <param name="sender">Source of the command event</param>
/// <param name="e">Event args for the command event</param>
private void DeleteCommand_ExecuteRequested(
    XamlUICommand sender, ExecuteRequestedEventArgs args)
{
    // If possible, remove specfied item from collection.
    if (args.Parameter != null)
    {
        foreach (var i in collection)
        {
            if (i.Text == (args.Parameter as string))
            {
                collection.Remove(i);
                return;
            }
        }
    }
    if (ListViewRight.SelectedIndex != -1)
    {
        collection.RemoveAt(ListViewRight.SelectedIndex);
    }
}
  1. Por último, definimos los controladores de varios eventos de ListView, incluidos PointerEntered, PointerExited y SelectionChanged.Finally, we define handlers for various ListView events, including PointerEntered, PointerExited, and SelectionChanged events. Los controladores de eventos de puntero se usan para mostrar u ocultar el botón Eliminar de cada elemento.The pointer event handlers are used to show or hide the Delete button for each item.
/// <summary>
/// Handler for the ListView selection changed event.
/// </summary>
/// <param name="sender">Source of the selection changed event</param>
/// <param name="e">Event args for the selection changed event</param>
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (ListViewRight.SelectedIndex != -1)
    {
        var item = collection[ListViewRight.SelectedIndex];
    }
}

/// <summary>
/// Handler for the pointer entered event.
/// Displays the delete item "hover" buttons.
/// </summary>
/// <param name="sender">Source of the pointer entered event</param>
/// <param name="e">Event args for the pointer entered event</param>
private void ListViewSwipeContainer_PointerEntered(
    object sender, PointerRoutedEventArgs e)
{
    if (e.Pointer.PointerDeviceType == 
        Windows.Devices.Input.PointerDeviceType.Mouse || 
        e.Pointer.PointerDeviceType == 
        Windows.Devices.Input.PointerDeviceType.Pen)
    {
        VisualStateManager.GoToState(
            sender as Control, "HoverButtonsShown", true);
    }
}

/// <summary>
/// Handler for the pointer exited event.
/// Hides the delete item "hover" buttons.
/// </summary>
/// <param name="sender">Source of the pointer exited event</param>
/// <param name="e">Event args for the pointer exited event</param>

private void ListViewSwipeContainer_PointerExited(
    object sender, PointerRoutedEventArgs e)
{
    VisualStateManager.GoToState(
        sender as Control, "HoverButtonsHidden", true);
}

Experiencias con comandos con la clase XamlUICommandCommand experiences using the XamlUICommand class

Si tienes que crear un comando que no está definido por la clase StandardUICommand, o quieres tener más control sobre la apariencia del comando, la clase XamlUiCommand deriva de la interfaz ICommand y agrega varias propiedades de interfaz de usuario (por ejemplo, icono, etiqueta, descripción y métodos abreviados de teclado), métodos y eventos para definir rápidamente la interfaz de usuario y el comportamiento de un comando personalizado.If you need to create a command that isn't defined by the StandardUICommand class, or you'd like more control over the command appearance, the XamlUiCommand class derives from the ICommand interface, adding various UI properties (such as an icon, label, description, and keyboard shortcuts), methods, and events to quickly define the UI and behavior of a custom command.

XamlUICommand permite especificar la interfaz de usuario mediante el enlace de controles tales como icono, etiqueta, descripción y métodos abreviado de teclado (tanto tecla de acceso como tecla de aceleración), sin tener que establecer las propiedades individuales.XamlUICommand lets you specify UI through the control binding, such as an icon, label, description, and keyboard shortcuts (both an access key and a keyboard accelerator), without setting the individual properties.

EjemploExample

Ejemplo de XamlUICommand

XamlUICommandSampleXamlUICommandSample

Descargar el código de este ejemploDownload the code for this example
Ejemplo de comandos de UWP (XamlUICommand)UWP commanding sample (XamlUICommand)

En este ejemplo se comparte la funcionalidad de eliminación del ejemplo StandardUICommand anterior, pero muestra cómo la clase XamlUICommand permite definir un comando de eliminación personalizado que usa su propia fuente, etiqueta, tecla de aceleración y descripción.This example shares the Delete functionality of the previous StandardUICommand example, but shows how the XamlUICommand class lets you define a custom delete command with your own font icon, label, keyboard accelerator, and description. Igual que en el ejemplo StandardUICommand, se muestra cómo mejorar un control ListView básico con el comando para eliminar elementos que se implementa mediante la clase XamlUICommand, al tiempo que se optimiza la experiencia del usuario para diversos tipos de entrada mediante controles MenuBar o Swipe, botones en los que mantener el puntero y menú contextual.Like the StandardUICommand example, we enhance a basic ListView with a Delete item command implemented through the XamlUICommand class, while optimizing the user experience for a variety of input types using a MenuBar, Swipe control, hover buttons, and context menu.

Muchos controles de plataforma utilizan las propiedades XamlUICommand en segundo plano, al igual que nuestro ejemplo StandardUICommand de la sección anterior.Many platform controls use the XamlUICommand properties under the covers, just like our StandardUICommand example in the previous section.

Nota

Este ejemplo requiere el paquete de NuGet Microsoft.UI.Xaml.Controls, que forma parte de la biblioteca de interfaz de usuario de Microsoft Windows.This sample requires the Microsoft.UI.Xaml.Controls NuGet package, a part of the Microsoft Windows UI Library.

Xaml:Xaml:

El ejemplo de interfaz de usuario incluye un control ListView con cinco elementos.The sample UI includes a ListView of five items. El comando XamlUICommand Delete está enlazado a MenuBarItem, SwipeItem, AppBarButton y un menú contextual.The custom XamlUICommand Delete is bound to a MenuBarItem, a SwipeItem, an AppBarButton, and ContextFlyout menu.

<Page
    x:Class="XamlUICommand_Sample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:XamlUICommand_Sample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:muxcontrols="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Page.Resources>
        <XamlUICommand x:Name="CustomXamlUICommand" 
                       ExecuteRequested="DeleteCommand_ExecuteRequested"
                       Description="Custom XamlUICommand" 
                       Label="Custom XamlUICommand">
            <XamlUICommand.IconSource>
                <FontIconSource FontFamily="Wingdings" Glyph="&#x4D;"/>
            </XamlUICommand.IconSource>
            <XamlUICommand.KeyboardAccelerators>
                <KeyboardAccelerator Key="D" Modifiers="Control"/>
            </XamlUICommand.KeyboardAccelerators>
        </XamlUICommand>

        <Style x:Key="HorizontalSwipe" 
               TargetType="ListViewItem" 
               BasedOn="{StaticResource ListViewItemRevealStyle}">
            <Setter Property="Height" Value="70"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
            <Setter Property="BorderThickness" Value="0"/>
        </Style>
        
    </Page.Resources>

    <Grid Loaded="ControlExample_Loaded" Name="MainGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <StackPanel Grid.Row="0" 
                    Padding="10" 
                    BorderThickness="0,0,0,1" 
                    BorderBrush="LightBlue"
                    Background="AliceBlue">
            <TextBlock Style="{StaticResource HeaderTextBlockStyle}">
                XamlUICommand sample
            </TextBlock>
            <TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,10">
                This sample shows how to use the XamlUICommand class to 
                share a custom command with consistent user experiences 
                across various controls.
            </TextBlock>
            <TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Margin="0,0,0,0">
                Specifically, we define a custom delete command and add it 
                to a variety of command surfaces, all of which share a common 
                icon, label, keyboard accelerator, and description.
            </TextBlock>
        </StackPanel>

        <muxcontrols:MenuBar Grid.Row="1">
            <muxcontrols:MenuBarItem Title="File">
            </muxcontrols:MenuBarItem>
            <muxcontrols:MenuBarItem Title="Edit">
                <MenuFlyoutItem x:Name="DeleteFlyoutItem" 
                                Command="{StaticResource CustomXamlUICommand}"/>
            </muxcontrols:MenuBarItem>
            <muxcontrols:MenuBarItem Title="Help">
            </muxcontrols:MenuBarItem>
        </muxcontrols:MenuBar>

        <ListView x:Name="ListViewRight" Grid.Row="2" 
                  Loaded="ListView_Loaded" 
                  IsItemClickEnabled="True"
                  SelectionMode="Single" 
                  SelectionChanged="ListView_SelectionChanged" 
                  ItemContainerStyle="{StaticResource HorizontalSwipe}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:ListItemData">
                    <UserControl PointerEntered="ListViewSwipeContainer_PointerEntered"
                                 PointerExited="ListViewSwipeContainer_PointerExited">
                        <UserControl.ContextFlyout>
                            <MenuFlyout>
                                <MenuFlyoutItem 
                                    Command="{x:Bind Command}" 
                                    CommandParameter="{x:Bind Text}" />
                            </MenuFlyout>
                        </UserControl.ContextFlyout>
                        <Grid AutomationProperties.Name="{x:Bind Text}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="HoveringStates">
                                    <VisualState x:Name="HoverButtonsHidden" />
                                    <VisualState x:Name="HoverButtonsShown">
                                        <VisualState.Setters>
                                            <Setter Target="HoverButton.Visibility" 
                                                    Value="Visible" />
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <SwipeControl x:Name="ListViewSwipeContainer">
                                <SwipeControl.RightItems>
                                    <SwipeItems Mode="Execute">
                                        <SwipeItem x:Name="DeleteSwipeItem"
                                                   Background="Red" 
                                                   Command="{x:Bind Command}" 
                                                   CommandParameter="{x:Bind Text}"/>
                                    </SwipeItems>
                                </SwipeControl.RightItems>
                                <Grid VerticalAlignment="Center">
                                    <TextBlock Text="{x:Bind Text}" 
                                               Margin="10" 
                                               FontSize="18" 
                                               HorizontalAlignment="Left"       
                                               VerticalAlignment="Center"/>
                                    <AppBarButton x:Name="HoverButton" 
                                                  IsTabStop="False" 
                                                  HorizontalAlignment="Right" 
                                                  Visibility="Collapsed" 
                                                  Command="{x:Bind Command}" 
                                                  CommandParameter="{x:Bind Text}"/>
                                </Grid>
                            </SwipeControl>
                        </Grid>
                    </UserControl>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

Código subyacenteCode-behind

  1. En primer lugar, definimos una clase ListItemData que contiene una cadena de texto e ICommand para cada ListViewItem de nuestro control ListView.First, we define a ListItemData class that contains a text string and ICommand for each ListViewItem in our ListView.
public class ListItemData
{
    public String Text { get; set; }
    public ICommand Command { get; set; }
}
  1. En la clase MainPage, definimos una colección de objetos ListItemData para la plantilla de datos DataTemplate de la plantilla ListView ItemTemplate.In the MainPage class, we define a collection of ListItemData objects for the DataTemplate of the ListView ItemTemplate. Después la rellenamos con una colección inicial de cinco elementos (con texto y el comando XamlUICommand asociado).We then populate it with an initial collection of five items (with text and associated XamlUICommand).
ObservableCollection<ListItemData> collection = new ObservableCollection<ListItemData>();

private void ControlExample_Loaded(object sender, RoutedEventArgs e)
{
    for (var i = 0; i < 5; i++)
    {
        collection.Add(
           new ListItemData { Text = "List item " + i.ToString(), Command = CustomXamlUICommand });
    }
}

private void ListView_Loaded(object sender, RoutedEventArgs e)
{
    var listView = (ListView)sender;
    listView.ItemsSource = collection;
}
  1. A continuación, definimos el controlador ExecuteRequested de ICommand donde se implementa el comando de eliminación de elementos.Next, we define the ICommand ExecuteRequested handler where we implement the item delete command.
private void DeleteCommand_ExecuteRequested(
   XamlUICommand sender, ExecuteRequestedEventArgs args)
{
    if (args.Parameter != null)
    {
        foreach (var i in collection)
        {
            if (i.Text == (args.Parameter as string))
            {
                collection.Remove(i);
                return;
            }
        }
    }
    if (ListViewRight.SelectedIndex != -1)
    {
        collection.RemoveAt(ListViewRight.SelectedIndex);
    }
}
  1. Por último, definimos los controladores de varios eventos de ListView, incluidos PointerEntered, PointerExited y SelectionChanged.Finally, we define handlers for various ListView events, including PointerEntered, PointerExited, and SelectionChanged events. Los controladores de eventos de puntero se usan para mostrar u ocultar el botón Eliminar de cada elemento.The pointer event handlers are used to show or hide the Delete button for each item.
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (ListViewRight.SelectedIndex != -1)
    {
        var item = collection[ListViewRight.SelectedIndex];
    }
}

private void ListViewSwipeContainer_PointerEntered(object sender, PointerRoutedEventArgs e)
{
    if (e.Pointer.PointerDeviceType == 
        Windows.Devices.Input.PointerDeviceType.Mouse || 
        e.Pointer.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Pen)
    {
        VisualStateManager.GoToState(sender as Control, "HoverButtonsShown", true);
    }
}

private void ListViewSwipeContainer_PointerExited(object sender, PointerRoutedEventArgs e)
{
    VisualStateManager.GoToState(sender as Control, "HoverButtonsHidden", true);
}

Experiencias con comandos con la interfaz ICommandCommand experiences using the ICommand interface

Los controles UWP estándar (botón, lista, selección, calendario, texto predictivo) proporcionan la base para muchas experiencias de comando comunes.Standard UWP controls (button, list, selection, calendar, predictive text) provide the basis for many common command experiences. Para ver la lista completa de tipos de controles, consulta Controles y patrones para aplicaciones de Windows.For a complete list of control types, see Controls and patterns for Windows apps.

La manera más sencilla de admitir una experiencia de comandos estructurada es definir una implementación de la interfaz ICommand (Windows.UI.Xaml.Input.ICommand para C++ o System.Windows.Input.ICommand para C#).The most basic way to support a structured commanding experience is to define an implementation of the ICommand interface (Windows.UI.Xaml.Input.ICommand for C++ or System.Windows.Input.ICommand for C#). Después, esta instancia de ICommand se puede enlazar a controles tales como botones.This ICommand instance can then be bound to controls such as buttons.

Nota

En algunos casos, podría ser igual de eficaz enlazar un método a evento Click y una propiedad a la propiedad IsEnabled.In some cases, it might be just as efficient to bind a method to the Click event and a property to the IsEnabled property.

EjemploExample

Ejemplo de la interfaz de comandos

Ejemplo de ICommandICommand example

Descargar el código de este ejemploDownload the code for this example
Ejemplo de comandos de UWP (ICommand)UWP commanding sample (ICommand)

En este ejemplo básico, se muestra cómo invocar un único comando con un clic de botón, una tecla de aceleración y girando la rueda del mouse.In this basic example, we demonstrate how a single command can be invoked with a button click, a keyboard accelerator, and rotating a mouse wheel.

Usamos dos controles ListView, uno con cinco elementos y otro vacío, y dos botones, uno para mover elementos desde el control ListView de la izquierda hasta el control ListView de la derecha, y el otro para mover los elementos de la derecha a izquierda.We use two ListViews, one populated with five items and the other empty, and two buttons, one for moving items from the ListView on the left to the ListView on the right, and the other for moving items from the right to the left. Cada botón está enlazado a un comando correspondiente (ViewModel.MoveRightCommand y ViewModel.MoveLeftCommand, respectivamente) y se habilitan y deshabilitan automáticamente en función del número de elementos que haya en el control ListView asociado.Each button is bound to a corresponding command (ViewModel.MoveRightCommand and ViewModel.MoveLeftCommand, respectively), and are enabled and disabled automatically based on the number of items in their associated ListView.

El código XAML siguiente define la interfaz de usuario para nuestro ejemplo.The following XAML code defines the UI for our example.

<Page
    x:Class="UICommand1.View.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="using:UICommand1.ViewModel"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Page.Resources>
        <vm:OpacityConverter x:Key="opaque" />
    </Page.Resources>

    <Grid Name="ItemGrid"
          Background="AliceBlue"
          PointerWheelChanged="Page_PointerWheelChanged">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView Grid.Column="0" VerticalAlignment="Center"
                  x:Name="CommandListView" 
                  ItemsSource="{x:Bind Path=ViewModel.ListItemLeft}" 
                  SelectionMode="None" IsItemClickEnabled="False" 
                  HorizontalAlignment="Right">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="vm:ListItemData">
                    <Grid VerticalAlignment="Center">
                        <AppBarButton Label="{x:Bind ListItemText}">
                            <AppBarButton.Icon>
                                <SymbolIcon Symbol="{x:Bind ListItemIcon}"/>
                            </AppBarButton.Icon>
                        </AppBarButton>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Grid Grid.Column="1" Margin="0,0,0,0"
              HorizontalAlignment="Center" 
              VerticalAlignment="Center">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="1">
                <FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" 
                          FontSize="40" Glyph="&#xE893;" 
                          Opacity="{x:Bind Path=ViewModel.ListItemLeft.Count, 
                                        Mode=OneWay, Converter={StaticResource opaque}}"/>
                <Button Name="MoveItemRightButton"
                        Margin="0,10,0,10" Width="120" HorizontalAlignment="Center"
                        Command="{x:Bind Path=ViewModel.MoveRightCommand}">
                    <Button.KeyboardAccelerators>
                        <KeyboardAccelerator 
                            Modifiers="Control" 
                            Key="Add" />
                    </Button.KeyboardAccelerators>
                    <StackPanel>
                        <SymbolIcon Symbol="Next"/>
                        <TextBlock>Move item right</TextBlock>
                    </StackPanel>
                </Button>
                <Button Name="MoveItemLeftButton" 
                            Margin="0,10,0,10" Width="120" HorizontalAlignment="Center"
                            Command="{x:Bind Path=ViewModel.MoveLeftCommand}">
                    <Button.KeyboardAccelerators>
                        <KeyboardAccelerator 
                            Modifiers="Control" 
                            Key="Subtract" />
                    </Button.KeyboardAccelerators>
                    <StackPanel>
                        <SymbolIcon Symbol="Previous"/>
                        <TextBlock>Move item left</TextBlock>
                    </StackPanel>
                </Button>
                <FontIcon FontFamily="{StaticResource SymbolThemeFontFamily}" 
                          FontSize="40" Glyph="&#xE892;"
                          Opacity="{x:Bind Path=ViewModel.ListItemRight.Count, 
                                        Mode=OneWay, Converter={StaticResource opaque}}"/>
            </StackPanel>
        </Grid>
        <ListView Grid.Column="2" 
                  x:Name="CommandListViewRight" 
                  VerticalAlignment="Center" 
                  IsItemClickEnabled="False" 
                  SelectionMode="None"
                  ItemsSource="{x:Bind Path=ViewModel.ListItemRight}" 
                  HorizontalAlignment="Left">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="vm:ListItemData">
                    <Grid VerticalAlignment="Center">
                        <AppBarButton Label="{x:Bind ListItemText}">
                            <AppBarButton.Icon>
                                <SymbolIcon Symbol="{x:Bind ListItemIcon}"/>
                            </AppBarButton.Icon>
                        </AppBarButton>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

Este es el código subyacente de la interfaz de usuario anterior.Here's the code-behind for the preceding UI.

En el código subyacente, nos conectamos a nuestro modelo de vista que contiene el código de comando.In code-behind, we connect to our view model that contains our command code. Además, definimos un controlador para la entrada desde la rueda del mouse, que también se conecta al código de nuestros comandos.In addition, we define a handler for input from the mouse wheel, which also connects our command code.

using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Controls;
using UICommand1.ViewModel;
using Windows.System;
using Windows.UI.Core;

namespace UICommand1.View
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        // Reference to our view model.
        public UICommand1ViewModel ViewModel { get; set; }

        // Initialize our view and view model.
        public MainPage()
        {
            this.InitializeComponent();
            ViewModel = new UICommand1ViewModel();
        }

        /// <summary>
        /// Handle mouse wheel input and assign our
        /// commands to appropriate direction of rotation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Page_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
        {
            var props = e.GetCurrentPoint(sender as UIElement).Properties;

            // Require CTRL key and accept only vertical mouse wheel movement 
            // to eliminate accidental wheel input.
            if ((Window.Current.CoreWindow.GetKeyState(VirtualKey.Control) != 
                CoreVirtualKeyStates.None) && !props.IsHorizontalMouseWheel)
            {
                bool delta = props.MouseWheelDelta < 0 ? true : false;

                switch (delta)
                {
                    case true:
                        ViewModel.MoveRight();
                        break;
                    case false:
                        ViewModel.MoveLeft();
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

Este es el código de nuestro modelo de vistaHere's the code from our view model

En nuestro modelo de vista definimos los detalles de ejecución de los dos comandos en nuestra aplicación: rellenar un control ListView y proporcionar un convertidor de valores de opacidad para ocultar o mostrar una interfaz de usuario adicional según el número de elementos de cada control ListView.Our view model is where we define the execution details for the two commands in our app, populate one ListView, and provide an opacity value converter for hiding or displaying some additional UI based on the item count of each ListView.

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace UICommand1.ViewModel
{
    /// <summary>
    /// UI properties for our list items.
    /// </summary>
    public class ListItemData
    {
        /// <summary>
        /// Gets and sets the list item content string.
        /// </summary>
        public string ListItemText { get; set; }
        /// <summary>
        /// Gets and sets the list item icon.
        /// </summary>
        public Symbol ListItemIcon { get; set; }
    }

    /// <summary>
    /// View Model that sets up a command to handle invoking the move item buttons.
    /// </summary>
    public class UICommand1ViewModel
    {
        /// <summary>
        /// The command to invoke when the Move item left button is pressed.
        /// </summary>
        public RelayCommand MoveLeftCommand { get; private set; }

        /// <summary>
        /// The command to invoke when the Move item right button is pressed.
        /// </summary>
        public RelayCommand MoveRightCommand { get; private set; }

        // Item collections
        public ObservableCollection<ListItemData> ListItemLeft { get; } = 
           new ObservableCollection<ListItemData>();
        public ObservableCollection<ListItemData> ListItemRight { get; } = 
           new ObservableCollection<ListItemData>();

        public ListItemData listItem;

        /// <summary>
        /// Sets up a command to handle invoking the move item buttons.
        /// </summary>
        public UICommand1ViewModel()
        {
            MoveLeftCommand = 
               new RelayCommand(new Action(MoveLeft), CanExecuteMoveLeftCommand);
            MoveRightCommand = 
               new RelayCommand(new Action(MoveRight), CanExecuteMoveRightCommand);

            LoadItems();
        }

        /// <summary>
        ///  Populate our list of items.
        /// </summary>
        public void LoadItems()
        {
            for (var x = 0; x <= 4; x++)
            {
                listItem = new ListItemData();
                listItem.ListItemText = "Item " + (ListItemLeft.Count + 1).ToString();
                listItem.ListItemIcon = Symbol.Emoji;
                ListItemLeft.Add(listItem);
            }
        }

        /// <summary>
        /// Move left command valid when items present in the list on right.
        /// </summary>
        /// <returns>True, if count is greater than 0.</returns>
        private bool CanExecuteMoveLeftCommand()
        {
            return ListItemRight.Count > 0;
        }

        /// <summary>
        /// Move right command valid when items present in the list on left.
        /// </summary>
        /// <returns>True, if count is greater than 0.</returns>
        private bool CanExecuteMoveRightCommand()
        {
            return ListItemLeft.Count > 0;
        }

        /// <summary>
        /// The command implementation to execute when the Move item right button is pressed.
        /// </summary>
        public void MoveRight()
        {
            if (ListItemLeft.Count > 0)
            {
                listItem = new ListItemData();
                ListItemRight.Add(listItem);
                listItem.ListItemText = "Item " + ListItemRight.Count.ToString();
                listItem.ListItemIcon = Symbol.Emoji;
                ListItemLeft.RemoveAt(ListItemLeft.Count - 1);
                MoveRightCommand.RaiseCanExecuteChanged();
                MoveLeftCommand.RaiseCanExecuteChanged();
            }
        }

        /// <summary>
        /// The command implementation to execute when the Move item left button is pressed.
        /// </summary>
        public void MoveLeft()
        {
            if (ListItemRight.Count > 0)
            {
                listItem = new ListItemData();
                ListItemLeft.Add(listItem);
                listItem.ListItemText = "Item " + ListItemLeft.Count.ToString();
                listItem.ListItemIcon = Symbol.Emoji;
                ListItemRight.RemoveAt(ListItemRight.Count - 1);
                MoveRightCommand.RaiseCanExecuteChanged();
                MoveLeftCommand.RaiseCanExecuteChanged();
            }
        }

        /// <summary>
        /// Views subscribe to this event to get notified of property updates.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notify subscribers of updates to the named property
        /// </summary>
        /// <param name="propertyName">The full, case-sensitive, name of a property.</param>
        protected void NotifyPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName);
                handler(this, args);
            }
        }
    }

    /// <summary>
    /// Convert a collection count to an opacity value of 0.0 or 1.0.
    /// </summary>
    public class OpacityConverter : IValueConverter
    {
        /// <summary>
        /// Converts a collection count to an opacity value of 0.0 or 1.0.
        /// </summary>
        /// <param name="value">The count passed in</param>
        /// <param name="targetType">Ignored.</param>
        /// <param name="parameter">Ignored</param>
        /// <param name="language">Ignored</param>
        /// <returns>1.0 if count > 0, otherwise returns 0.0</returns>
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return ((int)value > 0 ? 1.0 : 0.0);
        }

        /// <summary>
        /// Not used, converter is not intended for two-way binding. 
        /// </summary>
        /// <param name="value">Ignored</param>
        /// <param name="targetType">Ignored</param>
        /// <param name="parameter">Ignored</param>
        /// <param name="language">Ignored</param>
        /// <returns></returns>
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

Por último, es nuestra implementación de la interfaz ICommandFinally, here's our implementation of the ICommand interface

En este caso, definimos un comando que implementa la interfaz ICommand y simplemente retransmite su funcionalidad a otros objetos.Here, we define a command that implements the ICommand interface and simply relays its functionality to other objects.

using System;
using System.Windows.Input;

namespace UICommand1
{
    /// <summary>
    /// A command whose sole purpose is to relay its functionality 
    /// to other objects by invoking delegates. 
    /// The default return value for the CanExecute method is 'true'.
    /// <see cref="RaiseCanExecuteChanged"/> needs to be called whenever
    /// <see cref="CanExecute"/> is expected to return a different value.
    /// </summary>
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        /// <summary>
        /// Raised when RaiseCanExecuteChanged is called.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        /// <summary>
        /// Creates a new command that can always execute.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        public RelayCommand(Action execute)
            : this(execute, null)
        {
        }

        /// <summary>
        /// Creates a new command.
        /// </summary>
        /// <param name="execute">The execution logic.</param>
        /// <param name="canExecute">The execution status logic.</param>
        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        /// <summary>
        /// Determines whether this <see cref="RelayCommand"/> can execute in its current state.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require 
        /// data to be passed, this object can be set to null.
        /// </param>
        /// <returns>true if this command can be executed; otherwise, false.</returns>
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        /// <summary>
        /// Executes the <see cref="RelayCommand"/> on the current command target.
        /// </summary>
        /// <param name="parameter">
        /// Data used by the command. If the command does not require 
        /// data to be passed, this object can be set to null.
        /// </param>
        public void Execute(object parameter)
        {
            _execute();
        }

        /// <summary>
        /// Method used to raise the <see cref="CanExecuteChanged"/> event
        /// to indicate that the return value of the <see cref="CanExecute"/>
        /// method has changed.
        /// </summary>
        public void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
}

ResumenSummary

La Plataforma universal de Windows ofrece un sistema de comandos sólido y flexible que permite compilar aplicaciones que comparten y administran los comandos en distintos tipos de controles, dispositivos y tipos de entrada.The Universal Windows Platform provides a robust and flexible commanding system that lets you build apps that share and manage commands across control types, devices, and input types.

Usa los métodos siguientes para compilar comandos para tus aplicaciones de Windows:Use the following approaches when building commands for your Windows apps:

  • Escucha y controla los eventos en XAML y en el código subyacente.Listen for and handle events in XAML/code-behind
  • Enlaza a un método de control de eventos como Click.Bind to an event handling method such as Click
  • Define tu propia implementación de ICommand.Define your own ICommand implementation
  • Crea objetos XamlUICommand con tus propios valores para un conjunto predefinido de propiedades.Create XamlUICommand objects with your own values for a pre-defined set of properties
  • Crea objetos StandardUICommand con un conjunto predefinido de propiedades de plataforma y valores.Create StandardUICommand objects with a set of pre-defined platform properties and values

Pasos siguientesNext steps

Para ver un ejemplo completo que muestra una implementación de XamlUICommand y StandardUICommand, consulta el ejemplo Galería de controles XAML.For a complete example that demonstrates a XamlUICommand and StandardUICommand implementation, see the XAML Controls Gallery sample.

Consulta tambiénSee also

Controles y patrones para aplicaciones de WindowsControls and patterns for Windows apps

EjemplosSamples

Ejemplos del temaTopic samples

Otras muestrasOther samples