Übersicht über die Eingabe
Das Windows Presentation Foundation (WPF)-Subsystem stellt eine leistungsfähige API zum Abrufen von Inhalt von verschiedenen Geräten bereit, darunter Maus, Tastatur, Fingereingabe und Tablettstift. In diesem Thema werden die von WPF bereitgestellten Dienste beschrieben und die Architektur von Eingabesystemen erläutert.
Dieses Thema enthält folgende Abschnitte.
- Eingabe-API
- Ereignisrouting
- Behandeln von Eingabeereignissen
- Texteingabe
- Fingereingabe und Bearbeitung
- Focus
- Mausposition
- Mausauswahl
- Befehle
- Das Eingabesystem und die Basiselemente
- Weitere Informationen
- Verwandte Abschnitte
Eingabe-API
Die API-Bereitstellung für die primäre Eingabe findet sich in den Basiselementklassen: UIElement, ContentElement, FrameworkElement und FrameworkContentElement. Weitere Informationen zu den Basiselementen finden Sie unter Übersicht über Basiselemente. Diese Klassen bieten Funktionen für Eingabeereignisse, die sich auf Tastatureingaben, Maustasten, das Mausrad, die Mausbewegung, die Fokusverwaltung und die Mauszeigererkennung beziehen, um nur einige zu nennen. Indem die Eingabe-API auf den Basiselementen platziert wird, anstatt alle Eingabeereignisse als einen Dienst zu behandeln, ermöglicht es die Eingabearchitektur, dass die Eingabeereignisse ein bestimmtes Objekt in der Benutzeroberfläche als Quelle verwenden. Auf dieses Weise wird auch ein Schema zum Ereignisrouting unterstützt, bei dem mehr als ein Element ein Eingabeereignis verarbeiten kann. Vielen Eingabeereignissen ist ein Ereignispaar zugeordnet. So ist ein KeyDown-Ereignis beispielsweise mit dem KeyDown-Ereignis und dem PreviewKeyDown-Ereignis verknüpft. Der Unterschied zwischen diesen Ereignissen besteht darin, wie sie zum Zielelement weitergeleitet werden. Vorschauereignisse gehen anhand von Tunneling in der Elementstruktur vom Stammelement nach unten zum Zielelement. Bubbling-Ereignisse gehen anhand von Bubbling vom Zielelement nach oben zum Stammelement. Das Ereignisrouting in WPF wird weiter unten in dieser Übersicht und unter Übersicht über Routingereignisse ausführlicher erläutert.
Tastatur- und Mausklassen
Außer der Eingabe-API für Basiselementklassen bieten die Keyboard-Klasse und die Mouse-Klassen eine weitere API für die Tastatur- und Mauseingabe.
Beispiele für die Eingabe-API in der Keyboard-Klasse sind die Modifiers-Eigenschaft, mit der die derzeit gedrückten ModifierKeys zurückgegeben werden, und die IsKeyDown-Methode, die angibt, ob eine bestimmte Taste gedrückt wird.
Im folgenden Beispiel wird die GetKeyStates-Methode verwendet, um zu ermitteln, ob sich eine Key im gedrückten Zustand befindet.
' 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
// 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;
}
Beispiele für die Eingabe-API in der Mouse-Klasse sind MiddleButton, mit der der Zustand der mittleren Maustaste abgerufen wird, sowie DirectlyOver, wodurch das Element aufgerufen wird, über dem sich derzeit der Mauszeiger befindet.
Das folgende Beispiel ermittelt, ob sich die LeftButton der Maus im Pressed-Zustand befindet.
If Mouse.LeftButton = MouseButtonState.Pressed Then
UpdateSampleResults("Left Button Pressed")
End If
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
UpdateSampleResults("Left Button Pressed");
}
Die Mouse-Klasse und die Keyboard-Klasse werden im Laufe dieser Übersicht noch ausführlicher erläutert.
Tablettstifteingabe
WPF verfügt über die integrierte Unterstützung für den Stylus. Der Stylus ist ein Eingabegerät, das durch Tablet PC populär gemacht wurde. WPF-Anwendungen können den Tablettstift wie eine Maus behandeln, indem die Maus-API verwendet wird, wobei WPF jedoch auch eine Tablettstift-Geräteabstraktion bereitstellt, die ein ähnliches Modell wie für die Tastatur und die Maus verwendet. Alle auf den Tablettstift bezogenen APIs enthalten das Wort "Stylus".
Da der Tablettstift wie eine Maus verwendet werden kann, können einige Anwendungen, die nur die Mauseingabe unterstützen, automatisch auch den Tablettstift bis zu einem bestimmten Grad unterstützen. Wenn der Tablettstift auf diese Weise verwendet wird, wird der Anwendung ermöglicht, das entsprechende Tablettstiftereignis und dann das entsprechende Mausereignis zu verarbeiten. Darüber hinaus sind allgemeinere Dienste, wie zum Beispiel die Freihandeingabe, ebenfalls durch die Tablettstift-Geräteabstraktion verfügbar. Weitere Informationen zur Freihandeingabe finden Sie unter Erste Schritte mit Freihandeingaben.
Ereignisrouting
Ein FrameworkElement kann andere Elemente als untergeordnete Elemente im Inhaltsmodell enthalten, sodass sich eine Elementstruktur ergibt. In WPF kann das übergeordnete Element an Eingaben beteiligt sein, die sich an seine untergeordneten Elemente oder andere Nachfolgeelemente richten. Dies ist insbesondere dann nützlich, wenn Steuerelemente aus kleineren Steuerelementen erstellt werden sollen; dieser Vorgang wird als "Steuerelementzusammensetzung" oder "Compositing" bezeichnet. Weitere Informationen über Elementstrukturen und darüber, wie sich Elementstrukturen auf Ereignisrouten beziehen, finden Sie unter Strukturen in WPF.
Das Ereignisrouting bezeichnet den Vorgang, bei dem Ereignisse an mehrere Elemente weitergeleitet werden, sodass ein bestimmtes Objekt oder Element entlang der Route möglicherweise eine signifikante Antwort (durch Behandlung) auf ein Ereignis geben kann, das aus der Quelle eines anderen Elements stammt. Routingereignisse verwenden einen von drei Routingmechanismen: direkt, Bubbling und Tunneling. Beim direkten Routing wird das Quellelement als einziges Element benachrichtigt, und das Ereignis wird nicht an andere Elemente weitergeleitet. Das direkt geroutete Ereignis bietet jedoch trotzdem einige weitere Möglichkeiten, die nur für geroutete Ereignisse verfügbar sind, im Gegensatz zu standardmäßigen CLR-Ereignissen. Bubbling arbeitet sich in der Elementstruktur nach oben vor, indem zuerst das Element benachrichtigt wird, das Quelle des Ereignisses ist, dann das übergeordnete Element usw. Tunneling arbeitet sich vom Stamm der Elementstruktur nach unten vor und endet beim ursprünglichen Quellelement. Weitere Informationen zu Routingereignissen finden Sie unter Übersicht über Routingereignisse.
WPF-Eingabeereignisse bestehen in der Regel aus Paaren, die sich aus einem Tunneling- und einem Bubbling-Ereignis zusammensetzen. Tunneling-Ereignisse unterscheiden sich durch das "Preview"-Präfix von Bubbling-Ereignissen. So ist zum Beispiel PreviewMouseMove die Tunneling-Version eines Mausbewegungsereignisses und MouseMove die Bubbling-Version dieses Ereignisses. Diese Ereignispaare sind eine Konvention, die auf Elementebene implementiert ist und keine im WPF-Ereignissystem integrierte Funktion darstellt. Ausführliche Informationen finden Sie im Abschnitt zu WPF-Eingabeereignissen in Übersicht über Routingereignisse.
Behandeln von Eingabeereignissen
Um Eingaben für ein Element zu erhalten, muss ein Ereignishandler mit diesem speziellen Ereignis verknüpft sein. In XAML ist dies auf einfache Weise durchzuführen: Sie verweisen auf den Namen des Ereignisses als ein Attribut des Elements, das dieses Ereignis überwacht. Anschließend legen Sie den Wert des Attributs auf den Namen des von Ihnen definierten Ereignishandlers fest, basierend auf einem Delegaten. Der Ereignishandler muss in Code wie C# geschrieben werden und kann in einer Code-Behind-Datei enthalten sein.
Tastaturereignisse treten auf, wenn das Betriebssystem Tastaturaktionen meldet, die auftreten, während der Tastaturfokus auf einem Element liegt. Maus- und Tablettstiftereignisse lassen sich in zwei Kategorien einteilen: Ereignisse, die eine Änderung der Zeigerposition relativ zum Element melden, und Ereignisse, die Änderungen des Zustands der Gerätetasten melden.
Beispiel für Tastatureingabeereignisse
Im folgenden Beispiel wird ein Drücken der NACH-LINKS-TASTE überwacht. Es wird ein StackPanel erstellt, das über eine Button verfügt. An die Button-Instanz wird ein Ereignishandler angefügt, der das Drücken der NACH-LINKS-TASTE überwacht.
Im ersten Abschnitt des Beispiels werden der StackPanel und die Button erstellt, und der Ereignishandler für KeyDown wird angefügt.
<StackPanel>
<Button Background="AliceBlue"
KeyDown="OnButtonKeyDown"
Content="Button1"/>
</StackPanel>
' 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
// 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);
Der zweite Abschnitt ist in Code geschrieben und definiert den Ereignishandler. Wenn die NACH-LINKS-TASTE gedrückt wird und die Button den Tastaturfokus hat, wird der Handler ausgeführt, und die Background-Farbe der Button ändert sich. Wenn die Taste gedrückt wird, es sich jedoch nicht um die NACH-LINKS-TASTE handelt, ändert sich die Background-Farbe der Button-Taste wieder in die Anfangsfarbe.
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
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;
}
}
}
Beispiel für Mauseingabeereignisse
Im folgenden Beispiel ändert sich die Background-Farbe einer Button, wenn der Mauszeiger auf die Button geführt wird. Die Background-Farbe wird wieder zurückgesetzt, wenn der Mauszeiger von der Button weg bewegt wird.
Im ersten Abschnitt dieses Beispiels werden der StackPanel und das Button-Steuerelement erstellt, und der Ereignishandler für das MouseEnter-Ereignis und das MouseLeave-Ereignis wird der Button hinzugefügt.
<StackPanel>
<Button Background="AliceBlue"
MouseEnter="OnMouseExampleMouseEnter"
MouseLeave="OnMosueExampleMouseLeave">Button
</Button>
</StackPanel>
' 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
// 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);
Der zweite Abschnitt des Beispiels wird in Code geschrieben und definiert die Ereignishandler. Wenn der Mauszeiger auf die Button bewegt wird, ändert sich die Background-Farbe der Button in SlateGray. Wenn der Mauszeiger von der Button weg bewegt wird, ändert sich die Background-Farbe der Button zurück in AliceBlue.
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 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 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
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;
}
}
Texteingabe
Das TextInput-Ereignis ermöglicht Ihnen, die Texteingabe auf eine geräteunabhängige Weise zu überwachen. Die Tastatur ist die primäre Quelle für Texteingaben, wobei Sprach-, Handschrift- und andere Eingabegeräte ebenfalls Texteingaben generieren können.
Für die Tastatureingabe sendet WPF zuerst die entsprechenden KeyDown/KeyUp-Ereignisse. Wenn diese Ereignisse nicht verarbeitet werden und es sich bei der Taste um Text handelt (statt um eine Steuertaste wie zum Beispiel Richtungstasten oder Funktionstasten), wird ein TextInput-Ereignis ausgelöst. Es besteht nicht immer eine einfache Eins-zu-Eins-Zuordnung zwischen KeyDown/KeyUp-Ereignissen und TextInput-Ereignissen, da mehrere Tastatureingaben ein einzelnes Zeichen als Texteingabe und einzelne Tastatureingaben Zeichenfolgen generieren können. Dies trifft insbesondere auf Sprachen wie Chinesisch, Japanisch und Koreanisch zu, die Input Method Editors (IMEs) zum Generieren von Tausenden möglicher Zeichen entsprechend ihrem Alphabet verwenden.
Wenn WPF ein KeyUp/KeyDown-Ereignis sendet, wird Key auf Key.System festgelegt, wenn die Tastatureingaben Teil eines TextInput-Ereignisses werden könnten (wenn z. B. ALT+S gedrückt wird). Auf diese Weise wird dem Code in einem KeyDown-Ereignishandler ermöglicht, nach Key.System zu suchen; wenn dies gefunden wird, kann die Verarbeitung dem Handler des anschließend ausgelösten TextInput-Ereignisses überlassen werden. In diesem Fällen können die zahlreichen Eigenschaften des TextCompositionEventArgs-Arguments verwendet werden, um die ursprünglichen Tastatureingaben zu ermitteln. Ähnliches liegt vor, wenn ein IME aktiviert ist; Key weist den Wert Key.ImeProcessed auf, und ImeProcessedKey gibt die ursprüngliche Tastatureingabe bzw. die Tastatureingaben zurück.
Das folgende Beispiel definiert einen Handler für das Click-Ereignis und einen Handler für das KeyDown-Ereignis.
Das erste Segment des Codes oder Markups erstellt die Benutzeroberfläche.
<StackPanel KeyDown="OnTextInputKeyDown">
<Button Click="OnTextInputButtonClick"
Content="Open" />
<TextBox> . . . </TextBox>
</StackPanel>
' 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
// 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);
Das zweite Segment des Codes enthält die Ereignishandler.
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
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");
}
Da Eingabeereignisse mit Bubbling die Ereignisroute nach oben durchlaufen, empfängt der StackPanel die Eingabe unabhängig davon, auf welchem Element der Tastaturfokus liegt. Das TextBox-Steuerelement wird zuerst benachrichtigt, und der OnTextInputKeyDown-Handler wird nur dann aufgerufen, wenn das TextBox die Eingabe nicht verarbeitet hat. Wenn das PreviewKeyDown-Ereignis statt des KeyDown-Ereignisses versendet wird, wird zuerst der OnTextInputKeyDown-Handler aufgerufen.
In diesem Beispiel wird die Behandlungslogik zweimal geschrieben: einmal für STRG+O, und noch einmal für das Klickereignis der Schaltfläche. Dies kann durch die Verwendung von Befehlen vereinfacht werden, anstatt die Eingabeereignisse direkt zu behandeln. Befehle werden in dieser Übersicht und unter Befehlsübersicht erläutert.
Fingereingabe und Bearbeitung
Neue Hardware und API im Betriebssystem Windows 7 bieten Anwendungen die Möglichkeit, die Eingabe von mehreren Fingereingaben gleichzeitig zu empfangen. WPF ermöglicht Anwendungen das Erkennen und Reagieren auf Fingereingabe ähnlich wie auf andere Eingabe, z. B. mit Maus oder Tastatur, durch das Auslösen von Ereignissen bei der Fingereingabe.
WPF macht zwei Typen von Ereignissen bei Fingereingabe verfügbar: Berührungsereignisse und Bearbeitungsereignisse. Berührungsereignisse stellen Rohdaten zu jedem Finger auf einem Touchscreen und seiner Bewegung bereit. Bearbeitungsereignisse interpretieren die Eingabe als bestimmte Aktionen. Beide Typen von Ereignissen werden in diesem Abschnitt erläutert.
Erforderliche Komponenten
Sie benötigen die folgenden Komponenten, um eine Anwendung zu entwickeln, die auf Fingereingabe reagiert.
Microsoft Visual Studio 2010.
Windows 7.
Ein Gerät, z. B. ein Touchscreen, mit Windows Touch-Unterstützung.
Terminologie
Die folgenden Begriffe werden beim Erläutern der Fingereingabe verwendet.
Fingereingabe ist ein Typ von Benutzereingabe, die von Windows 7 erkannt wird. Normalerweise wird die Fingereingabe initiiert, indem Finger auf einen berührungsempfindlichen Bildschirm gelegt werden. Beachten Sie, dass Geräte wie Touchpads auf Laptops keine Fingereingabe unterstützen, wenn das Gerät die Position und Bewegung des Fingers lediglich als Mauseingabe konvertiert.
Mehrfingereingabe ist eine Fingereingabe, die gleichzeitig von mehreren Punkten erfolgt. Windows 7 und WPF unterstützen die Mehrfingereingabe. Beim Erläutern der Fingereingabe in der Dokumentation für WPF gelten die Konzepte für die Mehrfingereingabe.
Eine Bearbeitung erfolgt, wenn die Fingereingabe als auf ein Objekt angewendete physische Aktion interpretiert wird. In WPF interpretieren Bearbeitungsereignisse die Eingabe als Verschiebungs-, Erweiterungs- oder Drehungsbearbeitung.
Ein touch device stellt ein Objekt dar, das Fingereingaben produziert, z. B. ein Finger auf einem Touchscreen.
Steuerelemente, die auf Fingereingabe reagieren
Ein Bildlauf kann durch die folgenden Steuerelemente durchgeführt werden, indem ein Finger über dem Steuerelement gezogen wird, wenn teilweise nicht angezeigter Inhalt vorhanden ist.
ScrollViewer definiert die angefügte ScrollViewer.PanningMode-Eigenschaft, mit der Sie angeben können, ob die Verschiebung mit den Fingern vertikal, horizontal, in beide Richtungen oder in keine Richtung aktiviert ist. Die ScrollViewer.PanningDeceleration-Eigenschaft gibt an, wie schnell sich der Bildlauf verlangsamt, wenn der Benutzer den Finger vom Touchscreen hebt. Die angefügte ScrollViewer.PanningRatio-Eigenschaft gibt das Verhältnis des Bildlaufoffsets an, mit dem Bearbeitungsoffsets übersetzt werden.
Berührungsereignisse
Die Basisklassen UIElement, UIElement3D und ContentElement definieren Ereignisse, die Sie abonnieren können, damit die Anwendung auf Fingereingabe reagiert. Berührungsereignisse sind nützlich, wenn die Anwendung Fingereingabe als etwas Anderes interpretiert als das Bearbeiten eines Objekts. Eine Anwendung, mit der ein Benutzer mit einem oder mehreren Fingern zeichnen kann, würde z. B. Berührungsereignisse abonnieren.
Alle drei Klassen definieren die folgenden Ereignisse, die sich ähnlich verhalten, unabhängig von der definierenden Klasse.
Genau wie Tastatur- und Mausereignisse sind die Berührungsereignisse Routingereignisse. Die Ereignisse, die mit Preview beginnen, sind Tunneling-Ereignisse, und die Ereignisse, die mit Touch beginnen, sind Bubbling-Ereignisse. Weitere Informationen zu Routingereignissen finden Sie unter Übersicht über Routingereignisse. Beim Behandeln dieser Ereignisse können Sie die Position der Eingabe relativ zu einem Element durch Aufrufen der GetTouchPoint-Methode oder GetIntermediateTouchPoints-Methode abrufen.
Um die Interaktion zwischen den Berührungsereignissen zu verstehen, stellen Sie sich ein Szenario vor, bei dem ein Benutzer einen Finger auf ein Element legt, den Finger auf dem Element bewegt und dann den Finger vom Element hebt. Im Folgenden wird die Ausführung der Bubbling-Ereignisse dargestellt (die Tunneling-Ereignisse werden der Einfachheit halber weggelassen).
Fingereingabeereignisse
In der folgenden Auflistung wird die Sequenz der Ereignisse in der vorangehenden Abbildung beschrieben.
Das TouchEnter-Ereignis tritt einmal auf, wenn der Benutzer einen Finger auf das Element legt.
Das TouchDown-Ereignis tritt einmal auf.
Das TouchMove-Ereignis tritt mehrmals auf, wenn der Benutzer den Finger auf dem Element bewegt.
Das TouchUp-Ereignis tritt einmal auf, wenn der Benutzer den Finger vom Element hebt.
Das TouchLeave-Ereignis tritt einmal auf.
Werden mehr als zwei Finger verwendet, treten die Ereignisse für jeden Finger auf.
Bearbeitungsereignisse
Falls eine Anwendung einem Benutzer das Bearbeiten eines Objekts ermöglicht, definiert die UIElement-Klasse Bearbeitungsereignisse. Im Gegensatz zu den Berührungsereignissen, die einfach die Position der Fingereingabe melden, melden die Bearbeitungsereignisse, wie die Eingabe interpretiert werden kann. Es gibt die drei Bearbeitungstypen Verschiebung, Erweiterung und Drehung. Die folgende Liste beschreibt, wie die drei Bearbeitungstypen aufgerufen werden.
Legen Sie einen Finger auf ein Objekt, und bewegen Sie den Finger über dem Touchscreen, um eine Verschiebungsbearbeitung aufzurufen. Damit wird in der Regel das Objekt verschoben.
Legen Sie zwei Finger auf ein Objekt, und bewegen Sie die Finger zusammen oder auseinander, um eine Erweiterungsbearbeitung aufzurufen. Damit wird in der Regel die Größe des Objekts geändert.
Legen Sie zwei Finger auf ein Objekt, und drehen Sie die Finger umeinander, um eine Drehungsbearbeitung aufzurufen. Damit wird in der Regel das Objekt gedreht.
Mehrere Bearbeitungstypen können gleichzeitig auftreten.
Wenn Objekte auf Bearbeitungen reagieren, können Sie das Objekt träge erscheinen lassen. Dadurch können die Objekte die physische Welt simulieren. Beispielsweise bewegt sich beim Schieben eines Buch über einen Tisch das Buch weiter, wenn Sie kräftig genug schieben. WPF ermöglicht es Ihnen, dieses Verhalten durch das Auslösen von Bearbeitungsereignissen zu simulieren, nachdem die Finger des Benutzers das Objekt freigeben.
Informationen zum Erstellen einer Anwendung, mit der Benutzer ein Objekt verschieben, drehen oder die Größe ändern können, finden Sie unter Exemplarische Vorgehensweise: Erstellen der ersten Fingereingabeanwendung.
Das UIElement definiert die folgenden Bearbeitungsereignisse.
Standardmäßig erhält ein UIElement diese Bearbeitungsereignisse nicht. Um Bearbeitungsereignisse für ein UIElement zu erhalten, legen Sie UIElement.IsManipulationEnabled auf true fest.
Der Ausführungspfad von Bearbeitungsereignissen
Stellen Sie sich ein Szenario vor, bei dem ein Benutzer ein Objekt "wirft". Der Benutzer legt einen Finger auf das Objekt, bewegt den Finger eine kurze Entfernung über dem Touchscreen und hebt dann den Finger während der Bewegung. Das Ergebnis ist, dass sich das Objekt unter dem Finger des Benutzers bewegt und auch weiterhin bewegt, nachdem der Benutzer den Finger gehoben hat.
Im Folgenden werden der Ausführungspfad von Bearbeitungsereignissen und wichtige Informationen zu jedem Ereignis beschrieben.
Bearbeitungsereignisse
In der folgenden Auflistung wird die Sequenz der Ereignisse in der vorangehenden Abbildung beschrieben.
Das ManipulationStarting-Ereignis tritt auf, wenn der Benutzer einen Finger auf das Objekt legt. Unter anderem können Sie die ManipulationContainer-Eigenschaft mit diesem Ereignis festlegen. In den nachfolgenden Ereignissen ist die Position der Bearbeitung relativ zum ManipulationContainer. In anderen Ereignissen als ManipulationStarting ist diese Eigenschaft schreibgeschützt, deshalb ist das ManipulationStarting-Ereignis die einzige Gelegenheit zum Festlegen dieser Eigenschaft.
Das ManipulationStarted-Ereignis tritt anschließend ein. Dieses Ereignis meldet den Ursprung der Bearbeitung.
Das ManipulationDelta-Ereignis tritt mehrmals auf, wenn sich die Finger eines Benutzers auf einem Touchscreen bewegen. Die DeltaManipulation-Eigenschaft der ManipulationDeltaEventArgs-Klasse meldet, ob die Bearbeitung als Drehung, Erweiterung oder Verschiebung interpretiert wird. Hier erfolgt der größte Teil der Bearbeitung eines Objekts.
Das ManipulationInertiaStarting-Ereignis tritt ein, wenn die Finger des Benutzers den Kontakt mit dem Objekt verlieren. Dieses Ereignis ermöglicht es Ihnen, die Verlangsamung der Bearbeitungen während der Trägheit anzugeben. Damit kann das Objekt verschiedene physikalische Räume oder Attribute emulieren. Angenommen, die Anwendung verfügt über zwei Objekte, die zwei unterschiedlich schwere Elemente in der physischen Welt darstellen. Sie können festlegen, dass sich das schwerere Objekt schneller als das leichtere Objekt verlangsamt.
Das ManipulationDelta-Ereignis tritt mehrmals im Zusammenhang mit der Trägheit ein. Beachten Sie, dass dieses Ereignis eintritt, wenn sich die Finger des Benutzers über dem Touchscreen bewegen und wenn WPF Trägheit simuliert. Anders ausgedrückt, tritt ManipulationDelta vor und nach dem ManipulationInertiaStarting-Ereignis auf. Die ManipulationDeltaEventArgs.IsInertial-Eigenschaft meldet, ob das ManipulationDelta-Ereignis während der Trägheit auftritt, sodass Sie diese Eigenschaft überprüfen und je nach Wert verschiedene Aktionen ausführen können.
Das ManipulationCompleted-Ereignis tritt ein, wenn die Bearbeitung und die Trägheit endet. Das heißt, nachdem alle ManipulationDelta-Ereignisse aufgetreten sind, tritt das ManipulationCompleted-Ereignis ein, um den Abschluss der Bearbeitung anzuzeigen.
Das UIElement definiert auch das ManipulationBoundaryFeedback-Ereignis. Dieses Ereignis tritt ein, wenn die ReportBoundaryFeedback-Methode im ManipulationDelta-Ereignis aufgerufen wird. Das ManipulationBoundaryFeedback-Ereignis ermöglicht Anwendungen oder Komponenten das Bereitstellen von visuellem Feedback, wenn ein Objekt eine Begrenzung erreicht. Die Window-Klasse behandelt z. B. das ManipulationBoundaryFeedback-Ereignis, damit sich das Fenster leicht bewegt, wenn der Rand erreicht wird.
Sie können die Bearbeitung abbrechen, indem Sie die Cancel-Methode für die Ereignisargumente in jedem Bearbeitungsereignis außer dem ManipulationBoundaryFeedback-Ereignis aufrufen. Wenn Sie Cancel aufrufen, werden die Bearbeitungsereignisse nicht mehr ausgelöst, und bei Fingereingabe treten Mausereignisse auf. In der folgenden Tabelle wird die Beziehung zwischen dem Zeitpunkt des Abbruchs der Bearbeitung und den auftretenden Mausereignissen beschrieben.
Das Ereignis, bei dem das Abbrechen aufgerufen wurde |
Die Mausereignisse, die für bereits erfolgte Eingabe auftreten |
---|---|
Beim Drücken der Maustaste ausgelöste Ereignisse |
|
Beim Drücken der Maustaste und bei Änderung der Mauszeigerposition ausgelöste Ereignisse |
|
Beim Drücken der Maustaste, bei Änderung der Mauszeigerposition und beim Loslassen der Maustaste ausgelöste Ereignisse |
Beachten Sie, dass beim Aufrufen von Cancel, wenn die Bearbeitung in Trägheit ist, die Methode false zurückgibt und die Eingabe keine Mausereignisse auslöst.
Die Beziehung zwischen Fingereingabe- und Bearbeitungsereignissen
Ein UIElement kann immer Fingereingabeereignisse empfangen. Wenn die IsManipulationEnabled-Eigenschaft auf true festgelegt wird, können von einem UIElement Fingereingabe- und Bearbeitungsereignisse empfangen werden. Wenn das TouchDown-Ereignis (das heißt, die Handled-Eigenschaft ist false) nicht behandelt wird, erfasst die Bearbeitungsslogik die Fingereingabe für das Element und generiert die Bearbeitungsereignisse. Wenn die Handled-Eigenschaft im TouchDown-Ereignis auf true festgelegt wird, generiert die Bearbeitungslogik keine Bearbeitungsereignisse. Die folgende Abbildung zeigt die Beziehung zwischen Fingereingabe- und Bearbeitungsereignissen an.
Fingereingabe- und Bearbeitungsereignisse
Die folgende Liste beschreibt die Beziehung zwischen den Fingereingabe- und Manipulationsereignissen, die in der vorangehenden Abbildung gezeigt werden.
Wenn vom ersten Fingereingabegerät ein TouchDown-Ereignis für ein UIElement generiert wird, ruft die Bearbeitungslogik die CaptureTouch-Methode auf, die das GotTouchCapture-Ereignis generiert.
Wenn GotTouchCapture auftritt, ruft die Bearbeitungslogik die Manipulation.AddManipulator-Methode auf, die das ManipulationStarting-Ereignis generiert.
Wenn TouchMove-Ereignisse auftreten, werden von der Bearbeitungslogik die ManipulationDelta-Ereignisse erstellt, die vor dem ManipulationInertiaStarting-Ereignis auftreten.
Wenn vom letzten Fingereingabegerät des Elements das TouchUp-Ereignis ausgelöst wird, generiert die Bearbeitungslogik das ManipulationInertiaStarting-Ereignis.
Focus
Es gibt zwei Hauptkonzepte in Bezug auf den Fokus in WPF: den Tastaturfokus und den logischen Fokus.
Tastaturfokus
Tastaturfokus bezieht sich auf das Element, dem die Tastatureingabe gilt. Auf dem gesamten Desktop kann es nur ein Element mit Tastaturfokus geben. In WPF weist IsKeyboardFocused für das Element, das den Tastaturfokus besitzt, den Wert true auf. Die statische Keyboard-Methode FocusedElement gibt das Element zurück, das derzeit über den Tastaturfokus verfügt.
Der Tastaturfokus kann erhalten werden, indem mit der Tabstopptaste zu einem Element gewechselt wird oder indem mit der Maus auf bestimmte Elemente geklickt wird, wie z. B. TextBox. Der Tastaturfokus kann auch programmgesteuert über die Focus-Methode in der Keyboard-Klasse bezogen werden. Die Focus-Methode versucht, den Tastaturfokus auf das angegebene Element zu legen. Das von Focus zurückgegebene Element ist das Element, das derzeit über den Tastaturfokus verfügt.
Damit ein Element den Tastaturfokus erhalten kann, müssen die Focusable-Eigenschaft und die IsVisible-Eigenschaft auf true festgelegt sein. In einigen Klassen, wie z. B. Panel ist Focusable standardmäßig auf false festgelegt; Sie müssen diese Eigenschaft daher auf true festlegen, damit dieses Element den Fokus übernehmen kann.
Im folgenden Beispiel wird Focus verwendet, um den Tastaturfokus auf eine Button festzulegen. Am besten platzieren Sie den Anfangsfokus in einer Anwendung im Loaded-Ereignishandler.
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
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Sets keyboard focus on the first Button in the sample.
Keyboard.Focus(firstButton);
}
Weitere Informationen über den Tastaturfokus finden Sie unter Fokus - Übersicht.
Logischer Fokus
Der logische Fokus bezieht sich auf das FocusManager.FocusedElement in einem Fokusbereich. In einer Anwendung kann der logische Fokus auf mehreren Elementen liegen, innerhalb eines bestimmten Fokusbereichs kann jedoch immer nur ein Element den logischen Fokus haben.
Bei einem Fokusbereich handelt es sich um ein Containerelement, das das FocusedElement innerhalb seines Bereichs verfolgt. Wenn der Fokus einen Fokusbereich verlässt, verliert das fokussierte Element den Tastaturfokus, behält jedoch den logischen Fokus. Wenn der Fokus in den Fokusbereich zurückkehrt, erhält das fokussierte Element wieder den Tastaturfokus. Auf diese Weise kann der Tastaturfokus zwischen verschiedenen Fokusbereichen wechseln, wobei sichergestellt ist, dass das fokussierte Element im Fokusbereich den Tastaturfokus wieder erhält, wenn dieser in diesen Fokusbereich zurückkehrt.
Ein Element kann in Extensible Application Markup Language (XAML) in einen Fokusbereich umgewandelt werden, indem die mit dem FocusManager verknüpfte IsFocusScope-Eigenschaft auf true festgelegt wird, oder im Code, indem die verknüpfte Eigenschaft mit der SetIsFocusScope-Methode festgelegt wird.
Im folgenden Beispiel wird ein StackPanel in einen Fokusbereich umgewandelt, indem die angefügte IsFocusScope-Eigenschaft festgelegt wird.
<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>
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
Folgende Klassen in WPF sind standardmäßig Fokusbereiche: Window, Menu, ToolBar und ContextMenu
Ein Element, das über den Tastaturfokus verfügt, hat auch den logischen Fokus für den Fokusbereich, zu dem es gehört; daher wird beim Festlegen des Fokus auf ein Element mit der Focus-Methode in der Keyboard-Klasse oder der Basiselementklasse versucht, dem Element den Tastaturfokus und den logischen Fokus zuzuweisen.
Um das fokussierte Element in einem Fokusbereich zu bestimmen, verwenden Sie GetFocusedElement. Um das fokussierte Element für einen Fokusbereich zu ändern, verwenden Sie SetFocusedElement.
Weitere Informationen über den logischen Fokus finden Sie unter Fokus - Übersicht.
Mausposition
Die Eingabe-API von WPF bietet nützliche Informationen in Bezug auf Koordinatensysteme. So ist die Koordinate (0,0) beispielsweise die Koordinate oben links, jedoch oben links von welchem Element in der Struktur? Das Element, das das Eingabeziel ist? Das Element, an das Sie den Ereignishandler angefügt haben? Oder etwas anderes? Um eine Verwechslung zu vermeiden, erfordert die WPF-Eingabe-API die Angabe eines Referenzrahmens, wenn Sie mit Koordinaten arbeiten, die von der Maus abgeleitet werden. Die GetPosition-Methode gibt die Koordinate des Mauszeigers relativ zum angegebenen Element zurück.
Mausauswahl
Mausgeräte verfügen typischerweise über ein modales Merkmal, das als Mausauswahl bezeichnet wird. Die Mausauswahl wird verwendet, um einen vorübergehenden Eingabezustand beizubehalten, während ein Drag & Drop-Vorgang gestartet wird, damit nicht unbedingt andere Vorgänge auftreten, die die nominale Position des Mauszeigers auf dem Bildschirm betreffen. Während des Ziehens kann der Benutzer nicht klicken, ohne den Drag & Drop-Vorgang abzubrechen, wodurch die meisten Mauszeigerhinweise hinfällig werden, während die Mausauswahl vom Ursprung des Ziehens beibehalten wird. Das Eingabesystem stellt APIs bereit, die den Mausauswahlstatus ermitteln können, sowie APIs, die die Mausauswahl für ein bestimmtes Element erzwingen oder den Mausauswahlstatus löschen können. Weitere Informationen über Drag & Dropvorgänge finden Sie unter Übersicht über Drag & Drop.
Befehle
Befehle ermöglichen die Eingabebehandlung auf einer eher semantischen Ebene als die Geräteeingabe. Befehle sind einfache Direktiven, wie zum Beispiel Cut, Copy, Paste oder Open. Befehle sind nützlich, um die Befehlslogik zu zentralisieren. Auf den gleichen Befehl kann über ein Menu, in einer ToolBar oder über eine Tastenkombination zugegriffen werden. Befehle stellen außerdem eine Möglichkeit dar, Steuerelemente zu deaktivieren, wenn der Befehl nicht verfügbar ist.
RoutedCommand ist die WPF-Implementierung von ICommand. Wenn ein RoutedCommand ausgeführt wird, werden ein PreviewExecuted-Ereignis und ein Executed-Ereignis im Befehlsziel ausgelöst, die wie andere Eingaben auch mit Tunneling und Bubbling die Elementstruktur durchlaufen. Wenn kein Befehlsziel festgelegt ist, ist das Element mit dem Tastaturfokus das Befehlsziel. Die Logik, die den Befehl ausführt, wird an eine CommandBinding angefügt. Wenn ein Executed-Ereignis eine CommandBinding für den angegebenen Befehl erreicht, wird der ExecutedRoutedEventHandler der CommandBinding aufgerufen. Dieser Handler führt die Aktion für den Befehl aus.
Weitere Informationen über Befehle finden Sie unter Befehlsübersicht.
WPF stellt eine Bibliothek mit häufig verwendeten Befehlen bereit, die ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommands und EditingCommands umfasst; Sie können auch eigene Befehle definieren.
Das folgende Beispiel veranschaulicht, wie ein MenuItem so eingerichtet wird, dass beim Klicken darauf der Paste-Befehl für das TextBox ausgeführt wird, wobei davon ausgegangen wird, dass der Tastaturfokus auf dem TextBox liegt.
<StackPanel>
<Menu>
<MenuItem Command="ApplicationCommands.Paste" />
</Menu>
<TextBox />
</StackPanel>
' 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
// 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;
Weitere Informationen über Befehle in WPF finden Sie unter Befehlsübersicht.
Das Eingabesystem und die Basiselemente
Eingabeereignisse wie die angefügten Ereignisse, die von den Klassen Mouse, Keyboard und Stylus definiert werden, werden vom Eingabesystem ausgelöst und an einer bestimmten Position im Objektmodell eingefügt, basierend auf einem Treffertest der visuellen Struktur zur Laufzeit.
Jedes der Elemente, das von Mouse, Keyboard und Stylus als ein angefügtes Ereignis definiert wird, wird ebenfalls von der UIElement-Basiselementklasse und der ContentElement-Basiselementklasse als ein neues Routingereignis erneut verfügbar gemacht. Die Basiselement-Routingereignisse werden von Klassen generiert, die das ursprüngliche angefügte Ereignis verarbeiten und die Ereignisdaten wiederverwenden.
Wenn das Eingabeereignis durch seine Basiselement-Eingabeereignisimplementierung mit einem bestimmten Quellelement verknüpft wird, kann es durch den Rest einer Ereignisroute, die aus einer Kombination von logischen und visuellen Strukturobjekten besteht, geleitet und vom Anwendungscode verarbeitet werden. Im Allgemeinen ist es einfacher, diese gerätebezogenen Eingabeereignisse anhand der Routingereignisse für UIElement und ContentElement zu verarbeiten, da Sie eine intuitivere Ereignishandlersyntax sowohl im XAML als auch im Code verwenden können. Sie könnten auch entscheiden, stattdessen das angefügte Ereignis zu behandeln, das den Prozess initiiert hat, wobei dies jedoch verschiedene Probleme aufwirft: Das angefügte Ereignis ist möglicherweise für die Behandlung durch die Basiselementklasse markiert, und Sie müssen Accessormethoden statt echter Ereignissyntax verwenden, um Handler für angefügte Ereignisse anfügen zu können.
Weitere Informationen
Sie haben jetzt mehr über verschiedene Methoden zum Behandeln von Eingaben in WPF erfahren. Außerdem sollten Sie nun mehr über die verschiedenen Typen von Eingabeereignissen und die Routingereignismechanismen, die von WPF verwendet werden, wissen.
Es sind zusätzliche Ressourcen verfügbar, die WPF-Frameworkelemente und das Ereignisrouting noch ausführlicher erläutern. Weitere Informationen erhalten Sie in den folgenden Übersichten: Befehlsübersicht, Fokus - Übersicht, Übersicht über Basiselemente, Strukturen in WPF und Übersicht über Routingereignisse.
Siehe auch
Konzepte
Übersicht über Routingereignisse