Información general sobre acciones del usuario

El Windows Presentation Foundation (WPF) subsistema proporciona una API eficaz para obtener datos de una variedad de dispositivos, como el mouse, el teclado, la funcionalidad táctil y el lápiz óptico. En este tema se describen los servicios que proporciona WPF y se explica la arquitectura de los sistemas de entrada.

API de entrada

La exposición de la API de entrada principal se encuentra en las clases de elementos base: UIElement , ContentElement , FrameworkElement y FrameworkContentElement . Para obtener más información sobre los elementos base, consulte Información general sobre los elementos base. Estas clases proporcionan funcionalidad para los eventos de entrada relacionados con las pulsaciones de teclas, los botones del mouse, la rueda del mouse, el movimiento del mouse, la administración del foco, la captura del mouse, etc. Al colocar la API de entrada en los elementos base, en lugar de tratar todos los eventos de entrada como un servicio, la arquitectura de entrada permite que los eventos de entrada se propongan de un objeto determinado en la interfaz de usuario y para admitir un esquema de enrutamiento de eventos, por lo que más de un elemento tiene la oportunidad de controlar un evento de entrada. Muchos eventos de entrada tienen un par de eventos asociados. Por ejemplo, el evento de tecla abajo se asocia a KeyDown los PreviewKeyDown eventos y. La diferencia entre estos eventos radica en cómo se redirigen al elemento de destino. Los eventos de vista previa tunelizan el árbol de elementos desde el elemento raíz al de destino. Los eventos de propagación se propagan del elemento de destino al elemento raíz. El enrutamiento de eventos en WPF se describe con más detalle más adelante, dentro de esta información general, y en Información general sobre eventos enrutados.

Clases Keyboard y Mouse

Además de la API de entrada en las clases de elementos base, la Keyboard clase y Mouse las clases proporcionan una API adicional para trabajar con la entrada del mouse y del teclado.

Ejemplos de API de entrada en la Keyboard clase son la Modifiers propiedad, que devuelve el que ModifierKeys está presionado, y el IsKeyDown método, que determina si se presiona una tecla especificada.

En el ejemplo siguiente se usa el GetKeyStates método para determinar si un Key está en estado inactivo.

// Uses the Keyboard.GetKeyStates to determine if a key is down.
// A bitwise AND operation is used in the comparison.
// e is an instance of KeyEventArgs.
if ((Keyboard.GetKeyStates(Key.Return) & KeyStates.Down) > 0)
{
    btnNone.Background = Brushes.Red;
}
' Uses the Keyboard.GetKeyStates to determine if a key is down.
' A bitwise AND operation is used in the comparison. 
' e is an instance of KeyEventArgs.
If (Keyboard.GetKeyStates(Key.Return) And KeyStates.Down) > 0 Then
    btnNone.Background = Brushes.Red

Los ejemplos de la API de entrada en la Mouse clase son MiddleButton , que obtiene el estado del botón central del mouse, y DirectlyOver , que obtiene el elemento sobre el que se encuentra el puntero del mouse.

En el ejemplo siguiente se determina si el del LeftButton mouse está en el Pressed Estado.

if (Mouse.LeftButton == MouseButtonState.Pressed)
{
    UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
    UpdateSampleResults("Left Button Pressed")
End If

Las Mouse Keyboard clases y se describen con más detalle a lo largo de esta introducción.

Entrada del lápiz

WPF tiene compatibilidad integrada con Stylus . StylusEs una entrada manuscrita que el Tablet PC ha utilizado. WPF las aplicaciones pueden tratar el lápiz como un mouse mediante la API del mouse, pero WPF también expone una abstracción del dispositivo de lápiz óptico que usa un modelo similar al teclado y el mouse. Todas las API relacionadas con el lápiz óptico contienen la palabra "Stylus".

Dado que el lápiz puede actuar como un mouse, las aplicaciones que solo admiten la entrada de mouse pueden tener cierto nivel de compatibilidad con el lápiz automáticamente. Cuando se usa el lápiz de esta forma, la aplicación tiene la oportunidad de controlar el evento de lápiz adecuado y, a continuación, el evento de mouse correspondiente. Además, los servicios de nivel superior, como las entradas manuscritas, también están disponibles a través de la abstracción del dispositivo de lápiz. Para obtener más información sobre la escritura con lápiz como entrada, consulte Introducción a las entradas manuscritas.

Enrutamiento de eventos

Un FrameworkElement puede contener otros elementos como elementos secundarios en su modelo de contenido, formando un árbol de elementos. En WPF, el elemento primario puede participar en la entrada dirigida a sus elementos secundarios o a otros descendientes al controlar los eventos. Esto es especialmente útil para crear controles a partir de los controles más pequeños, un proceso conocido como "composición de controles" o "composición". Para obtener más información acerca de los árboles de elementos y cómo se relacionan con las rutas de eventos, consulte Árboles en WPF.

El enrutamiento de eventos es el proceso de reenviar eventos a varios elementos para que un objeto o elemento determinado de la ruta pueda elegir ofrecer una respuesta significativa (a través del control) a un evento que podría tener su origen en otro elemento. Los eventos enrutados usan uno de los tres mecanismos de enrutamiento: directo, propagación y tunelización. En el enrutamiento directo, el elemento de origen es el único elemento notificado y el evento no se redirige a ningún otro elemento. Sin embargo, el evento enrutado directo todavía ofrece algunas funcionalidades adicionales que solo están presentes para los eventos enrutados en lugar de los eventos CLR estándar. La propagación prepara el árbol de elementos: en primer lugar, notifica al elemento que dio origen al evento; a continuación, al elemento primario, etc. La tunelización comienza en la raíz del árbol de elementos y desciende para acabar con el elemento de origen original. Para obtener más información sobre los eventos enrutados, vea Información general sobre eventos enrutados.

Los eventos de entrada de WPF suelen encontrarse en parejas formadas por un evento de tunelización y otro de propagación. Los eventos de tunelización se distinguen de los eventos de propagación con el prefijo "Preview". Por ejemplo, PreviewMouseMove es la versión de tunelización de un evento de movimiento del mouse y MouseMove es la versión de propagación de este evento. Este emparejamiento de eventos es una convención que se implementa en el nivel de elemento y no es una funcionalidad propia del sistema de eventos de WPF. Para obtener más información, consulte la sección Eventos de entrada de WPF en Información general sobre eventos enrutados.

Control de eventos de entrada

Para recibir una entrada en un elemento, se debe asociar un controlador de eventos con el evento concreto. En XAML es sencillo: se debe hacer referencia al nombre del evento como atributo del elemento que se escuchará para este evento. A continuación, se establece el valor del atributo con el nombre del controlador de eventos que se define, en función de un delegado. El controlador de eventos debe escribirse en código como C# y puede incluirse en un archivo de código subyacente.

Los eventos de teclado tienen lugar cuando el sistema operativo notifica acciones de teclas que se producen mientras el foco del teclado está en un elemento. Los eventos de mouse y lápiz se dividen en dos categorías: eventos que informan de cambios en la posición del puntero en relación con el elemento y eventos que informan de cambios en el estado de los botones del dispositivo.

Ejemplo de evento de entrada de teclado

En el ejemplo siguiente se escucha una pulsación de tecla de flecha izquierda. StackPanelSe crea un que tiene un Button . Un controlador de eventos para escuchar la tecla de flecha izquierda se adjunta a la Button instancia.

La primera sección del ejemplo crea StackPanel y Button y asocia el controlador de eventos para KeyDown .

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
// Create the UI elements.
StackPanel keyboardStackPanel = new StackPanel();
Button keyboardButton1 = new Button();

// Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue;
keyboardButton1.Content = "Button 1";

// Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1);

// Attach event handler.
keyboardButton1.KeyDown += new KeyEventHandler(OnButtonKeyDown);
' Create the UI elements.
Dim keyboardStackPanel As New StackPanel()
Dim keyboardButton1 As New Button()

' Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue
keyboardButton1.Content = "Button 1"

' Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1)

' Attach event handler.
AddHandler keyboardButton1.KeyDown, AddressOf OnButtonKeyDown

La segunda sección está escrita en código y define el controlador de eventos. Cuando se presiona la tecla de dirección izquierda y el Button control tiene el foco de teclado, el controlador se ejecuta y Background se cambia el color de Button . Si se presiona la tecla, pero no es la tecla de dirección izquierda, el Background color de Button se vuelve a cambiar a su color inicial.

private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    Button source = e.Source as Button;
    if (source != null)
    {
        if (e.Key == Key.Left)
        {
            source.Background = Brushes.LemonChiffon;
        }
        else
        {
            source.Background = Brushes.AliceBlue;
        }
    }
}
Private Sub OnButtonKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    Dim source As Button = TryCast(e.Source, Button)
    If source IsNot Nothing Then
        If e.Key = Key.Left Then
            source.Background = Brushes.LemonChiffon
        Else
            source.Background = Brushes.AliceBlue
        End If
    End If
End Sub

Ejemplo de evento de entrada de mouse

En el ejemplo siguiente, el Background color de Button se cambia cuando el puntero del Mouse entra en Button . El Background color se restaura cuando el mouse sale de Button .

La primera sección del ejemplo crea y StackPanel el Button control y asocia los controladores de eventos para los MouseEnter MouseLeave eventos y al Button .

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button
          
  </Button>
</StackPanel>
// Create the UI elements.
StackPanel mouseMoveStackPanel = new StackPanel();
Button mouseMoveButton = new Button();

// Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue;
mouseMoveButton.Content = "Button";

// Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton);

// Attach event handler.
mouseMoveButton.MouseEnter += new MouseEventHandler(OnMouseExampleMouseEnter);
mouseMoveButton.MouseLeave += new MouseEventHandler(OnMosueExampleMouseLeave);
' Create the UI elements.
Dim mouseMoveStackPanel As New StackPanel()
Dim mouseMoveButton As New Button()

' Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue
mouseMoveButton.Content = "Button"

' Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton)

' Attach event handler.
AddHandler mouseMoveButton.MouseEnter, AddressOf OnMouseExampleMouseEnter
AddHandler mouseMoveButton.MouseLeave, AddressOf OnMosueExampleMouseLeave

La segunda sección del ejemplo está escrita en código y define los controladores de eventos. Cuando el Mouse entra Button en, el Background color de Button se cambia a SlateGray . Cuando el mouse sale de Button , el Background color de Button se vuelve a cambiar a AliceBlue .

private void OnMouseExampleMouseEnter(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.SlateGray;
    }
}
Private Sub OnMouseExampleMouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.SlateGray
    End If
End Sub
private void OnMosueExampleMouseLeave(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.AliceBlue;
    }
}
Private Sub OnMosueExampleMouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs)
    ' Cast the source of the event to a Button.
    Dim source As Button = TryCast(e.Source, Button)

    ' If source is a Button.
    If source IsNot Nothing Then
        source.Background = Brushes.AliceBlue
    End If
End Sub

Entrada de texto

El TextInput evento le permite escuchar la entrada de texto de forma independiente del dispositivo. El teclado es el medio principal de entrada de texto, pero la voz, la escritura a mano y otros dispositivos de entrada también pueden generar entradas de texto.

Para la entrada de teclado, WPF primero envía los KeyDown / KeyUp eventos correspondientes. Si no se controlan esos eventos y la clave es textual (en lugar de una tecla de control como flechas direccionales o teclas de función), TextInput se genera un evento. No siempre hay una asignación uno a uno simple entre KeyDown / KeyUp los eventos y, TextInput ya que varias pulsaciones de tecla pueden generar un solo carácter de entrada de texto y las pulsaciones de teclas únicas pueden generar cadenas de varios caracteres. Esto es especialmente cierto en el caso de idiomas como chino, Japonés y coreano que usan editores de métodos de entrada (IME) para generar los miles de caracteres posibles en sus alfabetos correspondientes.

Cuando WPF envía un KeyUp / KeyDown evento, Key se establece en Key.System si las pulsaciones de teclas pueden convertirse en parte de un TextInput evento (por ejemplo, si se presiona Alt + S). Esto permite que el código de un KeyDown controlador de eventos busque Key.System y, si se encuentra, deje el procesamiento para el controlador del TextInput evento generado posteriormente. En estos casos, las distintas propiedades del TextCompositionEventArgs argumento se pueden usar para determinar las pulsaciones de teclas originales. Del mismo modo, si un IME está activo, Key tiene el valor de Key.ImeProcessed y ImeProcessedKey proporciona la pulsación de tecla o pulsaciones de teclas originales.

En el ejemplo siguiente se define un controlador para el Click evento y un controlador para el KeyDown evento.

El primer segmento de código o marcado crea la interfaz de usuario.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
// Create the UI elements.
StackPanel textInputStackPanel = new StackPanel();
Button textInputeButton = new Button();
TextBox textInputTextBox = new TextBox();
textInputeButton.Content = "Open";

// Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton);
textInputStackPanel.Children.Add(textInputTextBox);

// Attach event handlers.
textInputStackPanel.KeyDown += new KeyEventHandler(OnTextInputKeyDown);
textInputeButton.Click += new RoutedEventHandler(OnTextInputButtonClick);
' Create the UI elements.
Dim textInputStackPanel As New StackPanel()
Dim textInputeButton As New Button()
Dim textInputTextBox As New TextBox()
textInputeButton.Content = "Open"

' Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton)
textInputStackPanel.Children.Add(textInputTextBox)

' Attach event handlers.
AddHandler textInputStackPanel.KeyDown, AddressOf OnTextInputKeyDown
AddHandler textInputeButton.Click, AddressOf OnTextInputButtonClick

El segundo segmento de código contiene los controladores de eventos.

private void OnTextInputKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.O && Keyboard.Modifiers == ModifierKeys.Control)
    {
        handle();
        e.Handled = true;
    }
}

private void OnTextInputButtonClick(object sender, RoutedEventArgs e)
{
    handle();
    e.Handled = true;
}

public void handle()
{
    MessageBox.Show("Pretend this opens a file");
}
Private Sub OnTextInputKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    If e.Key = Key.O AndAlso Keyboard.Modifiers = ModifierKeys.Control Then
        handle()
        e.Handled = True
    End If
End Sub

Private Sub OnTextInputButtonClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
    handle()
    e.Handled = True
End Sub

Public Sub handle()
    MessageBox.Show("Pretend this opens a file")
End Sub

Dado que los eventos de entrada propagan la ruta del evento, StackPanel recibe la entrada independientemente del elemento que tenga el foco de teclado. TextBoxPrimero se notifica al control y OnTextInputKeyDown se llama al controlador solo si no se TextBox controló la entrada. Si PreviewKeyDown se utiliza el evento en lugar del KeyDown evento, OnTextInputKeyDown primero se llama al controlador.

En este ejemplo, la lógica de control se escribe dos veces: una vez para CTRL+O y otra para el evento de clic del botón. Esto se puede simplificar mediante el uso de comandos, en lugar de controlar los eventos de entrada directamente. Los comandos se describen en esta información general y en Información general sobre comandos.

Funciones táctiles y manipulación

El nuevo hardware y la API en el sistema operativo Windows 7 proporcionan a las aplicaciones la capacidad de recibir entradas de varios toques simultáneamente. WPF permite que las aplicaciones detecten las funciones táctiles y respondan a ellas del mismo modo que con otras entradas, como el mouse o el teclado, y que generen eventos cuando se detecta un toque.

WPF expone dos tipos de eventos cuando se usa una función táctil: eventos de función táctil y eventos de manipulación. Los eventos de función táctil proporcionan datos sin procesar sobre cada dedo en una pantalla táctil y su movimiento. Los eventos de manipulación interpretan la entrada como determinadas acciones. Ambos tipos de eventos se describen en esta sección.

Requisitos previos

Para desarrollar una aplicación que responda a las funciones táctiles, necesitará los componentes siguientes.

  • Visual Studio 2010.

  • Windows 7.

  • Un dispositivo, como una pantalla táctil, compatible con Windows Touch.

Terminología

Para referirse a la función táctil, se usan los términos siguientes.

  • La función táctil es un tipo de entrada de usuario que reconoce Windows 7. Normalmente, se inicia colocando los dedos en una pantalla táctil. Tenga en cuenta que algunos dispositivos, como el panel táctil habitual en portátiles, no admiten la función táctil cuando se limitan a convertir la posición y el movimiento del dedo a entradas de mouse.

  • La función multitáctil es una función táctil que tiene lugar desde más de un punto de forma simultánea. Windows 7 y WPF admiten la función multitáctil. Cada vez que se menciona la función táctil en la documentación de WPF, los conceptos se aplican a la función multitáctil.

  • Una manipulación se produce cuando la función táctil se interpreta como una acción física que se aplica a un objeto. En WPF, los eventos de manipulación interpretan las entradas como una manipulación de traducción, expansión o rotación.

  • touch device representa un dispositivo que genera entradas táctiles, como un solo dedo en una pantalla táctil.

Controles que responden a la función táctil

Los siguientes controles se pueden desplazar al arrastrar un dedo por el control si tiene contenido que se desplaza fuera de la vista.

ScrollViewerDefine la ScrollViewer.PanningMode propiedad adjunta que le permite especificar si el movimiento panorámico táctil está habilitado horizontalmente, verticalmente, ambos o ninguno. La ScrollViewer.PanningDeceleration propiedad especifica la rapidez con la que se ralentiza el desplazamiento cuando el usuario levanta el dedo de la pantalla táctil. La ScrollViewer.PanningRatio propiedad adjunta especifica la relación entre el desplazamiento para traducir el desplazamiento de manipulación.

Eventos de funciones táctiles

Las clases base, UIElement , UIElement3D y ContentElement , definen eventos a los que se puede suscribir para que la aplicación responda a la entrada táctil. Los eventos de funciones táctiles resultan útiles cuando la aplicación interpreta la función táctil como algo distinto a la manipulación de un objeto. Por ejemplo, una aplicación que permite a un usuario dibujar con uno o más dedos podría suscribirse a los eventos de función táctil.

Las tres clases definen los siguientes eventos, que se comportan de forma similar, independientemente de la clase de definición.

Del mismo modo que los eventos de teclado y mouse, los eventos de función táctil son eventos enrutados. Los eventos que empiezan por Preview son eventos de tunelización, mientras que los que empiezan por Touch son eventos de propagación. Para obtener más información sobre los eventos enrutados, vea Información general sobre eventos enrutados. Al controlar estos eventos, puede obtener la posición de la entrada, relativa a cualquier elemento, llamando al GetTouchPoint GetIntermediateTouchPoints método o.

Para entender la interacción entre los eventos de función táctil, considere un escenario en que un usuario coloca un dedo en un elemento, lo mueve en el elemento y, a continuación, lo levanta. En la ilustración siguiente se muestra la ejecución de los eventos de propagación (los eventos de tunelización se omiten por motivos de simplicidad).

La secuencia de eventos de función táctil. Eventos de función táctil

En la lista siguiente se describe la secuencia de los eventos de la ilustración anterior.

  1. El TouchEnter evento se produce una vez cuando el usuario coloca un dedo en el elemento.

  2. El TouchDown evento se produce una vez.

  3. El TouchMove evento se produce varias veces cuando el usuario mueve el dedo dentro del elemento.

  4. El TouchUp evento se produce una vez cuando el usuario levanta el dedo del elemento.

  5. El TouchLeave evento se produce una vez.

Cuando se usan más de dos dedos, se producen eventos para cada dedo.

Eventos de manipulación

En los casos en los que una aplicación permite a un usuario manipular un objeto, la UIElement clase define los eventos de manipulación. A diferencia de los eventos de función táctil que, simplemente, notifican la posición de la función táctil, los eventos de manipulación indican cómo se puede interpretar la entrada. Hay tres tipos de manipulación: traducción, expansión y rotación. En la lista siguiente se describe cómo invocar los tres tipos de manipulaciones.

  • Coloque un dedo en un objeto y mueva el dedo por la pantalla táctil para invocar una manipulación de traducción. Normalmente, esto mueve el objeto.

  • Coloque dos dedos en un objeto y acérquelos o aléjelos para invocar una manipulación de expansión. Normalmente, esto cambia el tamaño del objeto.

  • Coloque dos dedos en un objeto y gírelos entre sí para invocar una manipulación de rotación. Normalmente, esto gira el objeto.

Se puede producir más de un tipo de manipulación al mismo tiempo.

Cuando hace que los objetos respondan a manipulaciones, puede hacer que parezca que el objeto tenga inercia. Esto puede hacer que los objetos simulen el mundo físico. Por ejemplo, si empuja un libro encima de una mesa con suficiente fuerza, el libro seguirá moviéndose cuando lo suelte. WPF le permite simular este comportamiento, ya que puede generar eventos de manipulación cuando los dedos del usuario liberan el objeto.

Para obtener información sobre cómo crear una aplicación que permita al usuario mover y girar un objeto, o cambiar su tamaño, consulte Tutorial: Crear su primera aplicación táctil.

UIElementDefine los siguientes eventos de manipulación.

De forma predeterminada, UIElement no recibe estos eventos de manipulación. Para recibir eventos de manipulación en un UIElement , establezca UIElement.IsManipulationEnabled en true .

Ruta de acceso de ejecución de eventos de manipulación

Considere un escenario en que un usuario "lanza" un objeto. El usuario coloca un dedo en el objeto, mueve el dedo por la pantalla táctil una distancia corta y, a continuación, lo levanta mientras se mueve. El resultado es que el objeto se moverá bajo el dedo del usuario y lo seguirá haciendo cuando el usuario lo levante.

En la ilustración siguiente se muestra la ruta de acceso de ejecución de los eventos de manipulación e información importante sobre cada evento.

La secuencia de eventos de manipulación. Eventos de manipulación

En la lista siguiente se describe la secuencia de los eventos de la ilustración anterior.

  1. El ManipulationStarting evento tiene lugar cuando el usuario coloca un dedo sobre el objeto. Entre otras cosas, este evento le permite establecer la ManipulationContainer propiedad. En los eventos posteriores, la posición de la manipulación será relativa a ManipulationContainer . En otros eventos distintos de ManipulationStarting , esta propiedad es de solo lectura, por lo que el ManipulationStarting evento es la única vez que se puede establecer esta propiedad.

  2. El ManipulationStarted evento tiene lugar a continuación. Este evento indica el origen de la manipulación.

  3. El ManipulationDelta evento se produce varias veces a medida que se mueven los dedos de un usuario en una pantalla táctil. La DeltaManipulation propiedad de la ManipulationDeltaEventArgs clase informa de si la manipulación se interpreta como movimiento, expansión o traducción. En este punto se realiza la mayoría del trabajo de manipulación de un objeto.

  4. El ManipulationInertiaStarting evento tiene lugar cuando los dedos del usuario pierden el contacto con el objeto. Este evento permite especificar la desaceleración de las manipulaciones durante la inercia. Esto sirve para que el objeto pueda emular espacios físicos o atributos diferentes, si así lo elige. Por ejemplo, suponga que la aplicación tiene dos objetos que representan elementos del mundo físico y que uno es más pesado que el otro. Puede hacer que el objeto más pesado disminuya su velocidad más rápidamente que el objeto ligero.

  5. El ManipulationDelta evento se produce varias veces a medida que se produce la inercia. Tenga en cuenta que este evento se produce cuando los dedos del usuario se mueven por la pantalla táctil y WPF simula la inercia. En otras palabras, ManipulationDelta se produce antes y después del ManipulationInertiaStarting evento. La ManipulationDeltaEventArgs.IsInertial propiedad indica si el ManipulationDelta evento se produce durante la inercia, de modo que puede comprobar esa propiedad y realizar diferentes acciones, en función de su valor.

  6. El ManipulationCompleted evento tiene lugar cuando finaliza la manipulación y cualquier inercia. Es decir, después de que se ManipulationDelta produzcan todos los eventos, ManipulationCompleted se produce el evento para indicar que se ha completado la manipulación.

UIElementTambién define el ManipulationBoundaryFeedback evento. Este evento se produce cuando ReportBoundaryFeedback se llama al método en el ManipulationDelta evento. El ManipulationBoundaryFeedback evento permite a las aplicaciones o componentes proporcionar comentarios visuales cuando un objeto alcanza un límite. Por ejemplo, la Window clase controla el ManipulationBoundaryFeedback evento para hacer que la ventana se mueva ligeramente cuando se encuentre su borde.

Puede cancelar la manipulación llamando al Cancel método en los argumentos del evento en cualquier evento de manipulación excepto en el ManipulationBoundaryFeedback evento. Cuando se llama a Cancel , los eventos de manipulación ya no se generan y se producen eventos del mouse para el toque. En la tabla siguiente se describe la relación entre el momento en que se cancela la manipulación y los eventos del mouse que se producen.

Evento con el que se llama al método Cancel Eventos del mouse que se generan para entradas que ya se han producido
ManipulationStarting y ManipulationStarted Eventos de presión del mouse.
ManipulationDelta Eventos de presión y movimiento del mouse.
ManipulationInertiaStarting y ManipulationCompleted Eventos de presión, movimiento y liberación del mouse.

Tenga en cuenta que si llama a Cancel cuando la manipulación está en inercia, el método devuelve false y la entrada no genera eventos del mouse.

Relación entre eventos de función táctil y manipulación

UIElementSiempre puede recibir eventos de toque. Cuando la IsManipulationEnabled propiedad se establece en true , UIElement puede recibir eventos de toque y manipulación. Si TouchDown no se controla el evento (es decir, la Handled propiedad es false ), la lógica de manipulación captura el toque en el elemento y genera los eventos de manipulación. Si la Handled propiedad se establece true en en el TouchDown evento, la lógica de manipulación no genera eventos de manipulación. En la siguiente ilustración se muestra la relación entre los eventos de función táctil y los de manipulación.

Relación entre los eventos de toque y manipulación Eventos de toque y manipulación

En la lista siguiente se describe la relación entre los eventos de función táctil y de manipulación que se muestra en la ilustración anterior.

Foco

Hay dos conceptos principales relacionados con el foco en WPF: el foco de teclado y el foco lógico.

Foco de teclado

El foco de teclado hace referencia al elemento que recibe la entrada del teclado. Puede haber un único elemento en todo el escritorio que tenga el foco de teclado. En WPF , el elemento que tiene el foco de teclado tendrá IsKeyboardFocused establecido en true . El Keyboard método estático FocusedElement devuelve el elemento que tiene actualmente el foco de teclado.

El foco de teclado se puede obtener haciendo tabulador a un elemento o haciendo clic con el mouse en determinados elementos, como TextBox . El foco de teclado también se puede obtener mediante programación con el Focus método en la Keyboard clase. Focus intenta proporcionar el foco de teclado del elemento especificado. El elemento devuelto por Focus es el elemento que tiene actualmente el foco de teclado.

Para que un elemento obtenga el foco de teclado Focusable , la propiedad y las IsVisible propiedades deben establecerse en true. Algunas clases, como Panel , tienen Focusable establecido en de false forma predeterminada; por lo tanto, puede que tenga que establecer esta propiedad en true si desea que ese elemento pueda obtener el foco.

En el ejemplo siguiente Focus se usa para establecer el foco de teclado en un Button . El lugar recomendado para establecer el foco inicial en una aplicación se encuentra en el Loaded controlador de eventos.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton)
End Sub

Para obtener más información acerca del foco de teclado, consulte Foco de teclado.

Foco lógico

El foco lógico hace referencia a FocusManager.FocusedElement en un ámbito de foco. Puede haber varios elementos que tengan el foco lógico en una aplicación, pero solo puede haber uno con el foco lógico en un ámbito de foco concreto.

Un ámbito de foco es un elemento contenedor que realiza un seguimiento de FocusedElement dentro de su ámbito. Cuando el foco sale de un ámbito de foco, el elemento enfocado pierde el foco de teclado, pero conserva el foco lógico. Cuando el foco vuelve al ámbito de foco, el elemento enfocado recibe el foco de teclado. Esto permite cambiar el foco de teclado entre varios ámbitos de foco, pero garantiza que el elemento enfocado dentro del ámbito siga siendo el elemento enfocado cuando vuelva el foco.

Un elemento se puede convertir en un ámbito de foco en estableciendo Lenguaje XAML (Extensible Application Markup Language) la FocusManager propiedad adjunta IsFocusScope en true , o en código estableciendo la propiedad adjunta mediante el SetIsFocusScope método.

En el ejemplo siguiente se convierte un StackPanel en un ámbito de foco estableciendo la IsFocusScope propiedad adjunta.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)

Las clases en WPF que son ámbitos de foco de forma predeterminada son Window , Menu , ToolBar y ContextMenu .

Un elemento que tiene el foco de teclado también tendrá el foco lógico del ámbito de foco al que pertenece; por lo tanto, establecer el foco en un elemento con el Focus método en la Keyboard clase o las clases de elementos base intentará proporcionar el foco de teclado y el foco lógico del elemento.

Para determinar el elemento con foco en un ámbito de foco, use GetFocusedElement . Para cambiar el elemento con foco de un ámbito de foco, use SetFocusedElement .

Para obtener más información acerca del foco lógico, consulte Foco lógico.

Posición del mouse

La WPF API de entrada proporciona información útil con respecto a los espacios de coordenadas. Por ejemplo, la coordenada (0,0) es la coordenada superior izquierda, pero ¿de qué elemento del árbol? ¿El elemento de destino de la entrada? ¿El elemento adjunto al controlador de eventos? ¿O alguna otra cosa? Para evitar confusiones, la WPF API de entrada requiere que especifique el marco de referencia al trabajar con las coordenadas obtenidas a través del mouse. El GetPosition método devuelve la coordenada del puntero del mouse en relación con el elemento especificado.

Captura del mouse

Los dispositivos de mouse tienen una característica modal concreta que se denomina captura del mouse. La captura del mouse se usa para mantener un estado de entrada transitorio cuando se inicia una operación de arrastrar y colocar, para que otras operaciones relacionadas con la posición en pantalla nominal del puntero del mouse no se produzcan necesariamente. Al arrastrar, el usuario no puede hacer clic sin anular la acción de arrastrar y colocar, lo que hace que la mayoría de las indicaciones que se producen al pasar el mouse sean inadecuadas mientras se conserva la captura del mouse desde el origen de la acción de arrastrar. El sistema de entrada expone las API que pueden determinar el estado de la captura del mouse, así como las API que pueden forzar la captura del mouse a un elemento concreto o borrar el estado de la captura del mouse. Para obtener más información sobre las operaciones de arrastrar y colocar, consulte Información general sobre la función de arrastrar y colocar.

Comandos:

Los comandos habilitan el control de entrada en un nivel más semántico que la entrada de dispositivos. Los comandos son directivas sencillas, como Cut, Copy, Paste o Open. Los comandos son útiles para centralizar la lógica de comando. Se puede tener acceso al mismo comando desde Menu , en ToolBar o mediante un método abreviado de teclado. Los comandos también proporcionan un mecanismo para deshabilitar controles cuando el comando deja de estar disponible.

RoutedCommand es la WPF implementación de ICommand . Cuando RoutedCommand se ejecuta un, PreviewExecuted Executed se genera un evento y en el destino del comando, que tuneliza y traspasa el árbol de elementos como otra entrada. Si no se define ningún destino de comando, el elemento con el foco de teclado será el destino del comando. La lógica que realiza el comando se adjunta a un CommandBinding . Cuando un Executed evento alcanza un CommandBinding para ese comando concreto, ExecutedRoutedEventHandler CommandBinding se llama a en. Este controlador realiza la acción del comando.

Para obtener más información sobre los comandos, consulte Información general sobre los comandos.

WPF proporciona una biblioteca de comandos comunes que consta de ApplicationCommands , MediaCommands , ComponentCommands , NavigationCommands y EditingCommands , o puede definir los suyos propios.

En el ejemplo siguiente se muestra cómo configurar un de MenuItem modo que, cuando se hace clic en él, se invoque el Paste comando en TextBox , suponiendo que TextBox tiene el foco de teclado.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

Para obtener más información sobre los comandos en WPF, consulte Información general sobre comandos.

Sistema de entrada y elementos base

Los eventos de entrada, como los eventos adjuntos definidos por las Mouse Keyboard clases, y, Stylus los genera el sistema de entrada y se insertan en una posición determinada en el modelo de objetos basándose en la prueba de posicionamiento del árbol visual en tiempo de ejecución.

Cada uno de los eventos que Mouse , Keyboard y Stylus define como un evento adjunto también se vuelve a exponer mediante las clases de elementos base UIElement y ContentElement como un nuevo evento enrutado. Los eventos enrutados de elementos base se generan desde clases que controlan el evento adjunto original y reutilizan los datos del evento.

Cuando el evento de entrada se asocia con un elemento de origen determinado a través de la implementación del evento de entrada de elemento base, se puede redirigir a través del resto de una ruta de evento que se basa en una combinación de objetos del árbol lógico y visual, y se puede controlar desde el código de la aplicación. Por lo general, es más conveniente controlar estos eventos de entrada relacionados con el dispositivo mediante los eventos enrutados en UIElement y ContentElement , porque puede usar la sintaxis de controlador de eventos más intuitiva en XAML y en el código. También puede elegir controlar el evento adjunto que inició el proceso, pero tendría que enfrentarse a varios problemas: el evento adjunto puede estar marcado como controlado por el control de la clase de elemento base, y debe utilizar métodos de descriptor de acceso, en lugar de la sintaxis de eventos true a fin de adjuntar controladores para eventos adjuntos.

Pasos siguientes

Ahora dispone de varias técnicas para controlar la entrada en WPF. También debe tener una mejor comprensión de los distintos tipos de eventos de entrada y los mecanismos de eventos enrutados que usa WPF.

Existen recursos adicionales que explican los elementos del marco de trabajo WPF y el enrutamiento de eventos con más detalle. Consulte los temas siguientes para obtener más información: Información general sobre comandos, Información general sobre el foco, Información general sobre elementos base, Árboles en WPF e Información general sobre eventos enrutados.

Consulte también