Invoeroverzicht
Het WPF-subsysteem (Windows Presentation Foundation) biedt een krachtige API voor het verkrijgen van invoer van verschillende apparaten, waaronder de muis, het toetsenbord, aanraakscherm en de stylus. In dit onderwerp worden de services van WPF beschreven en wordt de architectuur van de invoersystemen uitgelegd.
Invoer-API
De primaire invoer-API-blootstelling vindt u op de basiselementklassen: UIElement, ContentElement, FrameworkElementen FrameworkContentElement. Zie Overzicht van basiselementenvoor meer informatie over de basiselementen. Deze klassen bieden functionaliteit voor invoerevenementen met betrekking tot toetsdrukken, muisknoppen, muiswiel, muisbeweging, focusbeheer en muisopname, om er een paar te noemen. Door de invoer-API op de basiselementen te plaatsen, in plaats van alle invoergebeurtenissen als een service te behandelen, kunnen de invoergebeurtenissen worden opgehaald door een bepaald object in de gebruikersinterface en een gebeurtenisrouteringsschema ondersteunen waarbij meer dan één element de mogelijkheid heeft om een invoergebeurtenis te verwerken. Aan veel invoerevenementen zijn een paar gebeurtenissen gekoppeld. De key down-gebeurtenis is bijvoorbeeld gekoppeld aan de KeyDown en PreviewKeyDown gebeurtenissen. Het verschil in deze gebeurtenissen is de wijze waarop ze worden doorgestuurd naar het doelelement. Bekijk een voorbeeld van een gebeurtenistunnel in de elementstructuur van het hoofdelement naar het doelelement. Bubbelende gebeurtenissen gaan van het doelelement naar het hoofdelement. Gebeurtenisroutering in WPF wordt verderop in dit overzicht en in het Overzicht van gerouteerde gebeurtenissenbesproken.
Toetsenbord- en muisklassen
Naast de invoer-API op de basiselementklassen bieden de Keyboard-klasse en Mouse-klassen extra API voor het werken met toetsenbord- en muisinvoer.
Voorbeelden van invoer-API op de Keyboard-klasse zijn de eigenschap Modifiers, die de ModifierKeys die momenteel is ingedrukt, retourneert en de IsKeyDown methode, waarmee wordt bepaald of een opgegeven sleutel wordt ingedrukt.
In het volgende voorbeeld wordt de methode GetKeyStates gebruikt om te bepalen of een Key de status Offline heeft.
// 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
Voorbeelden van invoer-API op de Mouse-klasse zijn MiddleButton, waarmee de status van de middelste muisknop wordt opgehaald, en DirectlyOver, waarmee het element wordt opgehaald waar de muisaanwijzer zich momenteel boven bevindt.
In het volgende voorbeeld wordt bepaald of de LeftButton op de muis de status Pressed heeft.
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
UpdateSampleResults("Left Button Pressed")
End If
De Mouse- en Keyboard klassen worden in dit overzicht uitgebreider besproken.
Stylus-invoer
WPF heeft geïntegreerde ondersteuning voor de Stylus. De Stylus is een peninvoerapparaat dat populair is gemaakt door de Tablet PC. WPF-toepassingen kunnen de stylus behandelen als een muis met behulp van de muis-API, maar WPF maakt ook een stylus apparaatabstractie beschikbaar die een model gebruikt dat vergelijkbaar is met het toetsenbord en de muis. Alle stylus-gerelateerde API's bevatten het woord 'Stylus'.
Omdat de stylus kan fungeren als een muis, kunnen toepassingen die alleen muisinvoer ondersteunen, automatisch een bepaald niveau van stylusondersteuning verkrijgen. Wanneer de stylus op een dergelijke manier wordt gebruikt, krijgt de toepassing de mogelijkheid om de juiste stylus-gebeurtenis af te handelen en vervolgens de bijbehorende muis gebeurtenis af te handelen. Daarnaast zijn services op een hoger niveau, zoals inktinvoer, ook beschikbaar via de stylusapparaatabstractie. Zie Aan de slag met inktvoor meer informatie over inkt als invoer.
Gebeurtenisroutering
Een FrameworkElement kan andere elementen bevatten als onderliggende elementen in zijn inhoudsstructuur, waarmee een boomstructuur van elementen wordt gevormd. In WPF kan het bovenliggende element deelnemen aan invoer die is gericht op de onderliggende elementen of andere afstammelingen door gebeurtenissen te geven. Dit is vooral handig voor het bouwen van besturingselementen uit kleinere besturingselementen, een proces dat bekend staat als 'controlesamenstelling' of 'compositing'. Zie Trees in WPFvoor meer informatie over elementbomen en hoe elementstructuren betrekking hebben op gebeurtenisroutes.
Gebeurtenisroutering is het proces van het doorsturen van gebeurtenissen naar meerdere elementen, zodat een bepaald object of element langs de route ervoor kan kiezen om een aanzienlijk antwoord (via verwerking) te bieden aan een gebeurtenis die mogelijk is afkomstig van een ander element. Gerouteerde gebeurtenissen maken gebruik van een van de drie routeringsmechanismen: direct, bubbling en tunneling. Bij directe routering is het bronelement het enige element dat wordt gewaarschuwd en wordt de gebeurtenis niet doorgestuurd naar andere elementen. De direct gerouteerde gebeurtenis biedt echter nog enkele extra mogelijkheden die alleen aanwezig zijn voor gerouteerde gebeurtenissen in plaats van standaard CLR-gebeurtenissen. Bubbling werkt de elementstructuur omhoog door eerst het element op de hoogte te stellen dat de gebeurtenis heeft veroorzaakt, vervolgens het bovenliggende element, enzovoort. Tunneling begint bij de hoofdmap van de elementstructuur en werkt omlaag, eindigend op het oorspronkelijke bronelement. Zie Overzicht van gerouteerde gebeurtenissenvoor meer informatie over gerouteerde gebeurtenissen.
WPF-invoergebeurtenissen komen over het algemeen in paren, bestaande uit een tunneling- en een bubblinggebeurtenis. Tunnelinggebeurtenissen onderscheiden zich van bubblinggebeurtenissen door middel van het voorvoegsel 'Preview'. PreviewMouseMove is bijvoorbeeld de tunnelingversie van een muisverplaatsingsevenement en MouseMove de bubblingversie van deze gebeurtenis is. Deze gebeurteniskoppeling is een conventie die wordt geïmplementeerd op elementniveau en is geen inherente mogelijkheid van het WPF-gebeurtenissysteem. Zie de sectie WPF-invoergebeurtenissen in Overzicht van gerouteerde gebeurtenissenvoor meer informatie.
Invoerevenementen verwerken
Als u invoer voor een element wilt ontvangen, moet een gebeurtenis-handler aan die specifieke gebeurtenis zijn gekoppeld. In XAML is dit eenvoudig: u verwijst naar de naam van de gebeurtenis als een kenmerk van het element dat naar deze gebeurtenis luistert. Vervolgens stelt u de waarde van het kenmerk in op de naam van de gebeurtenis-handler die u definieert, op basis van een gemachtigde. De gebeurtenis-handler moet worden geschreven in code zoals C# en kan worden opgenomen in een code-behind-bestand.
Toetsenbord gebeurtenissen treden op wanneer het besturingssysteem belangrijke acties rapporteert die optreden terwijl de toetsenbordfocus zich op een element bevindt. Muis- en stylusgebeurtenissen worden elk onderverdeeld in twee categorieën: gebeurtenissen die wijzigingen rapporteren in de positie van de aanwijzer ten opzichte van het element en gebeurtenissen die wijzigingen rapporteren in de status van apparaatknoppen.
Voorbeeld van toetsenbordgebeurtenis
In het volgende voorbeeld wordt geluisterd naar het indrukken van de linker pijltjestoets. Er wordt een StackPanel gecreëerd dat een Buttonheeft. Een evenementhandler voor het luisteren naar de linker pijltjestoets wordt gekoppeld aan het Button-exemplaar.
In het eerste gedeelte van het voorbeeld worden de StackPanel en de Button aangemaakt en de gebeurtenishandler gekoppeld aan de 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
De tweede sectie is geschreven in code en definieert de gebeurtenis-handler. Wanneer de linker pijl-toets wordt ingedrukt en Button de toetsenbordfocus heeft, wordt de handler uitgevoerd en verandert de kleur Background van Button. Als de toets wordt ingedrukt, maar het is niet de linker pijltoets, wordt de kleur Background van de Button weer gewijzigd in de oorspronkelijke kleur.
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
Voorbeeld van gebeurtenis voor muisinvoer
In het volgende voorbeeld wordt de Background kleur van een Button gewijzigd wanneer de muiswijzer de Buttoninvoert. De Background kleur wordt hersteld wanneer de muis de Buttonverlaat.
In het eerste gedeelte van het voorbeeld worden het besturingselement StackPanel en het besturingselement Button aangemaakt en worden de event handlers voor de gebeurtenissen MouseEnter en MouseLeave gekoppeld aan de 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
De tweede sectie van het voorbeeld is geschreven in code en definieert de gebeurtenis-handlers. Wanneer de muis de Buttonbinnenkomt, wordt de Background kleur van de Button gewijzigd in SlateGray. Wanneer de muis de Buttonverlaat, wordt de Background kleur van de Button weer gewijzigd in 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
Tekstinvoer
Met de gebeurtenis TextInput kunt u op een apparaatonafhankelijke manier naar tekstinvoer luisteren. Het toetsenbord is de primaire methode voor tekstinvoer, maar spraak, handschrift en andere invoerapparaten kunnen ook tekstinvoer genereren.
Voor toetsenbordinvoer verzendt WPF eerst de juiste KeyDown/KeyUp gebeurtenissen. Als deze gebeurtenissen niet worden verwerkt en de sleutel tekstueel is (in plaats van een besturingstoets zoals directionele pijlen of functietoetsen), wordt er een TextInput gebeurtenis gegenereerd. Er is niet altijd een eenvoudige een-op-een toewijzing tussen KeyDown/KeyUp en TextInput gebeurtenissen, omdat meerdere toetsaanslagen één teken van tekstinvoer kunnen genereren en een enkele toetsaanslag tekenreeksen met meerdere tekens kan genereren. Dit geldt met name voor talen zoals Chinees, Japans en Koreaans die gebruikmaken van Input Method Editors (IME's) om de duizenden mogelijke tekens in hun bijbehorende alfabetten te genereren.
Wanneer WPF een KeyUp/KeyDown-gebeurtenis verzendt, wordt Key ingesteld op Key.System als de toetsaanslagen deel kunnen uitmaken van een TextInput gebeurtenis (als alt+S bijvoorbeeld wordt ingedrukt). Hierdoor kan code in een KeyDown gebeurtenis-handler controleren op Key.System en, indien gevonden, de verwerking overlaten aan de handler van de vervolgens gegenereerde TextInput-gebeurtenis. In deze gevallen kunnen de verschillende eigenschappen van het argument TextCompositionEventArgs worden gebruikt om de oorspronkelijke toetsaanslagen te bepalen. Als een IME actief is, heeft Key de waarde van Key.ImeProcesseden geeft ImeProcessedKey de oorspronkelijke toetsaanslag of toetsaanslagen.
In het volgende voorbeeld wordt een handler gedefinieerd voor de Click gebeurtenis en een handler voor de KeyDown gebeurtenis.
Met het eerste code- of markeringssegment wordt de gebruikersinterface gemaakt.
<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
Het tweede codesegment bevat de gebeurtenis-handlers.
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
Omdat invoergebeurtenissen de gebeurtenisroute doorgeven, ontvangt StackPanel de invoer, ongeacht welk element de toetsenbordfocus heeft. Het TextBox besturingselement wordt eerst gewaarschuwd en de OnTextInputKeyDown
handler wordt alleen aangeroepen als de TextBox de invoer niet heeft verwerkt. Als de PreviewKeyDown gebeurtenis wordt gebruikt in plaats van de KeyDown gebeurtenis, wordt de OnTextInputKeyDown
handler eerst aangeroepen.
In dit voorbeeld wordt de verwerkingslogica twee keer geschreven, één keer voor Ctrl+O, en nogmaals voor de klik-gebeurtenis van de knop. Dit kan worden vereenvoudigd met behulp van opdrachten, in plaats van de invoer gebeurtenissen rechtstreeks te verwerken. Opdrachten worden in dit overzicht en in Commanding Overviewbesproken.
Aanraken en manipuleren
Nieuwe hardware en API in het Windows 7-besturingssysteem bieden toepassingen de mogelijkheid om tegelijkertijd invoer van meerdere aanrakingen te ontvangen. WPF stelt toepassingen in staat om aanraking te detecteren en erop te reageren op een manier die vergelijkbaar is met het reageren op andere invoer, zoals de muis of het toetsenbord, door gebeurtenissen te genereren wanneer aanraking plaatsvindt.
WPF maakt twee soorten gebeurtenissen beschikbaar wanneer aanraking plaatsvindt: aanraak-gebeurtenissen en manipulatie-gebeurtenissen. Aanraakevenementen bieden onbewerkte gegevens over elke vinger op een touchscreen en de beweging ervan. Manipulatie-gebeurtenissen interpreteren de invoer als bepaalde acties. Beide typen gebeurtenissen worden in deze sectie besproken.
Voorwaarden
U hebt de volgende onderdelen nodig om een toepassing te ontwikkelen die reageert op aanraken.
Visual Studio 2010.
Windows 7.
Een apparaat, zoals een touchscreen, dat Ondersteuning biedt voor Windows Touch.
Terminologie
De volgende termen worden gebruikt wanneer aanraking wordt besproken.
Touch is een type gebruikersinvoer dat wordt herkend door Windows 7. Meestal wordt aanraking gestart door vingers op een aanraakgevoelig scherm te plaatsen. Houd er rekening mee dat apparaten zoals een touchpad die gebruikelijk zijn op laptopcomputers, geen ondersteuning bieden voor aanraking als het apparaat alleen de positie en beweging van de vinger converteert als muisinvoer.
Multitouch is een aanraking die op meer dan één punt tegelijkertijd plaatsvindt. Windows 7 en WPF ondersteunt multitouch. Wanneer aanraking wordt besproken in de documentatie voor WPF, zijn de concepten van toepassing op multitouch.
Een manipulatie optreedt wanneer aanraking wordt geïnterpreteerd als een fysieke actie die wordt toegepast op een object. In WPF interpreteren manipulatie-gebeurtenissen invoer als een vertaling, uitbreiding of rotatiemanipulatie.
Een
touch device
vertegenwoordigt een apparaat dat aanraakinvoer produceert, zoals één vinger op een touchscreen.
Besturingselementen die reageren op aanraken
De volgende besturingselementen kunnen worden gescrold door een vinger over het besturingselement te slepen als deze inhoud bevat die buiten de weergave wordt geschoven.
De ScrollViewer definieert de ScrollViewer.PanningMode gekoppelde eigenschap waarmee u kunt opgeven of aanraakpanning horizontal, verticaal, beide of geen van beide is ingeschakeld. De eigenschap ScrollViewer.PanningDeceleration geeft aan hoe snel het schuiven vertraagt wanneer de gebruiker de vinger van het touchscreen haalt. De gekoppelde eigenschap ScrollViewer.PanningRatio specificeert de verhouding van de scrollafwijking tot de verplaatsingsafwijking door manipulatie.
Aanraakevenementen
De basisklassen, UIElement, UIElement3Den ContentElement, definiëren gebeurtenissen waarop u zich kunt abonneren, zodat uw toepassing reageert op aanraking. Touch-gebeurtenissen zijn handig wanneer uw toepassing aanraakscherm interpreteert als iets anders dan het bewerken van een object. Een toepassing waarmee een gebruiker met een of meer vingers kan tekenen, zou zich bijvoorbeeld abonneren op aanraakevenementen.
Alle drie de klassen definiëren de volgende gebeurtenissen, die zich op dezelfde manier gedragen, ongeacht de definitieklasse.
Net als toetsenbord- en muisgebeurtenissen zijn ook de aanraakgebeurtenissen gerouteerde gebeurtenissen. De gebeurtenissen die beginnen met Preview
zijn tunnelingsevenementen en de gebeurtenissen die beginnen met Touch
zijn bubbling-gebeurtenissen. Zie Overzicht van gerouteerde gebeurtenissenvoor meer informatie over gerouteerde gebeurtenissen. Wanneer u deze gebeurtenissen verwerkt, kunt u de positie van de invoer, ten opzichte van elk element, ophalen door de methode GetTouchPoint of GetIntermediateTouchPoints aan te roepen.
Als u de interactie tussen de aanraakevenementen wilt begrijpen, kunt u het scenario overwegen waarin een gebruiker één vinger op een element plaatst, de vinger in het element beweegt en vervolgens de vinger van het element opheft. In de volgende afbeelding ziet u de uitvoering van de bubblinggebeurtenissen (de tunnelinggebeurtenissen worden voor het gemak weggelaten).
Aanraakevenementen
In de volgende lijst wordt de volgorde beschreven van de gebeurtenissen in de vorige afbeelding.
De TouchEnter gebeurtenis treedt één keer op wanneer de gebruiker een vinger op het element plaatst.
De TouchDown gebeurtenis vindt eenmalig plaats.
De TouchMove gebeurtenis vindt meerdere keren plaats wanneer de gebruiker de vinger binnen het element verplaatst.
De gebeurtenis TouchUp treedt één keer op wanneer de gebruiker de vinger van het element haalt.
De TouchLeave gebeurtenis vindt eenmalig plaats.
Wanneer er meer dan twee vingers worden gebruikt, vinden de gebeurtenissen plaats voor elke vinger.
Manipulatiegebeurtenissen
Voor gevallen waarin een toepassing een gebruiker in staat stelt een object te bewerken, definieert de UIElement klasse manipulatie-gebeurtenissen. In tegenstelling tot de aanraakgebeurtenissen die simpelweg de positie van aanraking rapporteren, rapporteren de manipulatiegebeurtenissen hoe de invoer kan worden geïnterpreteerd. Er zijn drie soorten manipulaties, vertaling, uitbreiding en rotatie. In de volgende lijst wordt beschreven hoe u de drie typen manipulaties aanroept.
Plaats een vinger op een object en beweeg de vinger over het touchscreen om een vertaalmanipulatie aan te roepen. Dit verplaatst het object meestal.
Plaats twee vingers op een object en beweeg de vingers dichter bij elkaar of verder van elkaar om een uitbreidingsmanipulatie aan te roepen. Dit wijzigt meestal het formaat van het object.
Plaats twee vingers op een object en draai de vingers om elkaar heen om een rotatiemanipulatie aan te roepen. Dit draait meestal om het object.
Meer dan één type manipulatie kan tegelijkertijd plaatsvinden.
Wanneer u ervoor zorgt dat objecten reageren op manipulaties, kunt u ervoor zorgen dat het object traagheid heeft. Hierdoor kunnen uw objecten de fysieke wereld simuleren. Wanneer u bijvoorbeeld een boek over een tafel duwt, blijft het boek bewegen als u hard genoeg duwt nadat u het hebt losgelaten. Met WPF kunt u dit gedrag simuleren door manipulatiegebeurtenissen te genereren nadat de vingers van de gebruiker het object loslaat.
Zie Walkthrough: Het Creëren van Uw Eerste Touch Applicatievoor informatie over het maken van een toepassing waarmee de gebruiker een object kan verplaatsen, het formaat ervan kan wijzigen en draaien.
De UIElement definieert de volgende manipulatie-gebeurtenissen.
Standaard ontvangt een UIElement deze manipulatie-gebeurtenissen niet. Als u manipulatie-gebeurtenissen op een UIElementwilt ontvangen, stelt u UIElement.IsManipulationEnabled in op true
.
Het uitvoeringspad van manipulatie-gebeurtenissen
Overweeg een scenario waarin een gebruiker een object gooit. De gebruiker plaatst een vinger op het object, beweegt de vinger over het touchscreen voor een korte afstand en tilt vervolgens de vinger op terwijl het beweegt. Het resultaat hiervan is dat het object onder de vinger van de gebruiker wordt verplaatst en blijft bewegen nadat de gebruiker de vinger heeft opgeheven.
In de volgende afbeelding ziet u het uitvoeringspad van manipulatie-gebeurtenissen en belangrijke informatie over elke gebeurtenis.
Manipulatie-gebeurtenissen
In de volgende lijst wordt de volgorde beschreven van de gebeurtenissen in de vorige afbeelding.
De gebeurtenis ManipulationStarting treedt op wanneer de gebruiker een vinger op het object plaatst. Met deze gebeurtenis kunt u onder andere de eigenschap ManipulationContainer instellen. In de volgende gebeurtenissen is de positie van de manipulatie relatief ten opzichte van de ManipulationContainer. In andere gebeurtenissen dan ManipulationStartingis deze eigenschap alleen-lezen, dus de ManipulationStarting gebeurtenis is de enige keer dat u deze eigenschap kunt instellen.
De ManipulationStarted gebeurtenis vindt vervolgens plaats. Deze gebeurtenis rapporteert de oorsprong van de manipulatie.
De ManipulationDelta gebeurtenis vindt meerdere keren plaats wanneer de vingers van een gebruiker op een touchscreen bewegen. De eigenschap DeltaManipulation van de ManipulationDeltaEventArgs klasse rapporteert of de manipulatie wordt geïnterpreteerd als beweging, uitbreiding of vertaling. Hier voert u het meeste werk uit van het bewerken van een object.
De ManipulationInertiaStarting gebeurtenis treedt op wanneer de vingers van de gebruiker het contact met het object verliezen. Met deze gebeurtenis kunt u de vertraging van de manipulaties tijdens traagheid opgeven. Dit is zo dat uw object verschillende fysieke spaties of kenmerken kan emuleren als u kiest. Stel dat uw toepassing twee objecten heeft die items in de fysieke wereld vertegenwoordigen en één is zwaarder dan de andere. U kunt het zwaardere object sneller vertragen dan het lichtere object.
De ManipulationDelta gebeurtenis vindt meerdere keren plaats wanneer traagheid plaatsvindt. Houd er rekening mee dat deze gebeurtenis zich voordoet wanneer de vingers van de gebruiker over het touchscreen bewegen en wanneer WPF traagheid simuleert. Met andere woorden, ManipulationDelta plaatsvindt vóór en na de ManipulationInertiaStarting gebeurtenis. De ManipulationDeltaEventArgs.IsInertial eigenschap rapporteert of de ManipulationDelta gebeurtenis plaatsvindt tijdens traagheid, zodat u die eigenschap kunt controleren en verschillende acties kunt uitvoeren, afhankelijk van de waarde.
De ManipulationCompleted gebeurtenis treedt op wanneer de manipulatie en eventuele inertie eindigen. Na alle ManipulationDelta gebeurtenissen treedt de ManipulationCompleted gebeurtenis op om aan te geven dat de manipulatie is voltooid.
De UIElement definieert ook de ManipulationBoundaryFeedback gebeurtenis. Deze gebeurtenis treedt op wanneer de methode ReportBoundaryFeedback wordt aangeroepen in de ManipulationDelta gebeurtenis. Met de gebeurtenis ManipulationBoundaryFeedback kunnen toepassingen of onderdelen visuele feedback geven wanneer een object een grens bereikt. De Window-klasse verwerkt bijvoorbeeld de ManipulationBoundaryFeedback gebeurtenis om ervoor te zorgen dat het venster enigszins wordt verplaatst wanneer de rand wordt aangetroffen.
U kunt de manipulatie annuleren door de methode Cancel aan te roepen voor de gebeurtenisargumenten in elke manipulatie-gebeurtenis, behalve ManipulationBoundaryFeedback gebeurtenis. Wanneer u Cancelaanroept, worden de manipulatiegebeurtenissen niet meer gegenereerd en worden aanraakgebeurtenissen als muisgebeurtenissen behandeld. In de volgende tabel wordt de relatie beschreven tussen de tijd waarop de manipulatie wordt geannuleerd en de muisgebeurtenissen die optreden.
De gebeurtenis waarin Annuleren wordt aangeroepen | De muisgebeurtenissen die optreden voor invoer die al heeft plaatsgevonden |
---|---|
ManipulationStarting en ManipulationStarted | Muisklik-gebeurtenissen |
ManipulationDelta | Muis omlaag en gebeurtenissen verplaatsen met de muis. |
ManipulationInertiaStarting en ManipulationCompleted | Muis omlaag, muis bewegen en gebeurtenissen met de muis omhoog. |
Houd er rekening mee dat als u Cancel aanroept wanneer de manipulatie traag is, de methode false
retourneert en de invoer geen muis-gebeurtenissen genereert.
De relatie tussen aanraak- en manipulatie-gebeurtenissen
Een UIElement kan altijd aanraakevenementen ontvangen. Wanneer de eigenschap IsManipulationEnabled is ingesteld op true
, kan een UIElement zowel aanraak- als manipulatie-gebeurtenissen ontvangen. Als de TouchDown gebeurtenis niet wordt verwerkt (dat wil gezegd, de eigenschap Handled is false
), legt de manipulatielogica de aanraking vast op het element en genereert de manipulatiegebeurtenissen. Als de eigenschap Handled is ingesteld op true
in de gebeurtenis TouchDown, genereert de manipulatielogica geen manipulatie-gebeurtenissen. In de volgende afbeelding ziet u de relatie tussen aanraak- en manipulatie-gebeurtenissen.
Aanraak- en manipulatie-gebeurtenissen
In de volgende lijst wordt de relatie beschreven tussen de aanraak- en manipulatie-gebeurtenissen die in de vorige afbeelding worden weergegeven.
Wanneer het eerste aanraakapparaat een TouchDown gebeurtenis op een UIElementgenereert, roept de manipulatielogica de CaptureTouch-methode aan, waarmee de GotTouchCapture gebeurtenis wordt gegenereerd.
Wanneer de GotTouchCapture optreedt, roept de manipulatielogica de Manipulation.AddManipulator-methode aan, waarmee de ManipulationStarting gebeurtenis wordt gegenereerd.
Wanneer de TouchMove gebeurtenissen optreden, genereert de manipulatielogica de ManipulationDelta gebeurtenissen die plaatsvinden vóór de ManipulationInertiaStarting gebeurtenis.
Wanneer het laatste aanraakapparaat op het element de TouchUp gebeurtenis genereert, genereert de manipulatielogica de ManipulationInertiaStarting gebeurtenis.
Focus
Er zijn twee hoofdconcepten die betrekking hebben op focus in WPF: toetsenbordfocus en logische focus.
Toetsenbordfocus
De focus van het toetsenbord verwijst naar het element dat toetsenbordinvoer ontvangt. Er kan slechts één element op het hele bureaublad zijn met toetsenbordfocus. In WPF heeft het element met toetsenbordfocus IsKeyboardFocused ingesteld op true
. De statische methode KeyboardFocusedElement retourneert het element dat momenteel de toetsenbordfocus heeft.
U kunt de toetsenbordfocus verkrijgen door op tabs te drukken op een element of door met de muis op bepaalde elementen te klikken, zoals een TextBox. Toetsenbordfocus kan ook programmatisch worden verkregen met behulp van de methode Focus op de Keyboard klasse. Focus probeert het opgegeven element de toetsenbordfocus te geven. Het element dat door Focus wordt geretourneerd, is het element dat momenteel de toetsenbordfocus heeft.
Om een element toetsenbordfocus te laten krijgen, moeten de eigenschap Focusable en de eigenschappen IsVisible worden ingesteld op true. Sommige klassen, zoals Panel, hebben Focusable standaard ingesteld op false
; Daarom moet u deze eigenschap mogelijk instellen op true
als u wilt dat dat element de focus kan krijgen.
In het volgende voorbeeld wordt Focus gebruikt om de toetsenbordfocus op een Buttonin te stellen. De aanbevolen plaats voor het instellen van de eerste focus in een toepassing bevindt zich in de Loaded evenementenhandler.
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
Zie Overzicht van focusvoor meer informatie over toetsenbordfocus.
Logische focus
Logische focus verwijst naar de FocusManager.FocusedElement in een focusbereik. Er kunnen meerdere elementen zijn die logische focus hebben in een toepassing, maar er kan maar één element zijn dat logische focus heeft in een bepaald focusbereik.
Een focus-bereik is een containerelement dat de FocusedElement binnen zijn focus-bereik bijhoudt. Wanneer de focus een focusbereik verlaat, verliest het focuselement zijn toetsenbordfocus, maar blijft het logische focus behouden. Wanneer de focus terugkeert naar het focusbereik, krijgt het focuselement de toetsenbordfocus. Hierdoor kan de toetsenbordfocus worden gewijzigd tussen meerdere focusbereiken, maar zorgt u ervoor dat het focuselement binnen het focusbereik het focuselement blijft wanneer de focus wordt geretourneerd.
Een element kan worden omgezet in een focusbereik in Extensible Application Markup Language (XAML) door de eigenschap FocusManager gekoppelde eigenschap in te stellen IsFocusScope op true
of in code door de gekoppelde eigenschap in te stellen met behulp van de methode SetIsFocusScope.
In het volgende voorbeeld wordt een StackPanel een focusbereik door het instellen van de gekoppelde eigenschap IsFocusScope.
<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)
Klassen in WPF die standaard focusbereiken zijn, zijn Window, Menu, ToolBaren ContextMenu.
Een element met toetsenbordfocus heeft ook een logische focus binnen het focusbereik waartoe het behoort. Daarom zal het instellen van de focus op een element met de Focus-methode op de Keyboard-klasse of op de basiselementklassen proberen zowel toetsenbordfocus als logische focus aan het element toe te kennen.
Gebruik GetFocusedElementom het focuselement in een focusbereik te bepalen. Als u het focuselement voor een focusbereik wilt wijzigen, gebruikt u SetFocusedElement.
Zie Overzicht van focusvoor meer informatie over logische focus.
Muispositie
De WPF-invoer-API biedt nuttige informatie met betrekking tot coördinaatruimten. Coördinaat (0,0)
is bijvoorbeeld de coördinaat linksboven, maar de linkerbovenhoek van welk element in de boom? Het element dat het invoerdoel is? Het element waaraan u de gebeurtenis-handler hebt gekoppeld? Of iets anders? Om verwarring te voorkomen, vereist de WPF-invoer-API dat u uw referentiekader opgeeft wanneer u met coördinaten werkt die via de muis zijn verkregen. De methode GetPosition retourneert de coördinaat van de muis aanwijzer ten opzichte van het opgegeven element.
Muisklavierregistratie
Muisapparaten houden specifiek een modaal kenmerk vast, ook wel muisopname genoemd. Muisopname wordt gebruikt om een overgangsinvoerstatus te behouden wanneer een bewerking voor slepen en neerzetten wordt gestart, zodat andere bewerkingen met betrekking tot de nominale positie op het scherm van de muisaanwijzer niet noodzakelijkerwijs plaatsvinden. Tijdens het slepen kan de gebruiker niet klikken zonder het slepen-en-neerzetten-proces te beëindigen, waardoor de meeste muisover meldingen ongepast zijn terwijl de muisbeheersing wordt vastgehouden door de oorsprong van het slepen. Het invoersysteem maakt API's beschikbaar die de status van de muisopname kunnen bepalen, evenals API's die het vastleggen van de muis kunnen afdwingen naar een specifiek element of de status van het vastleggen van de muis wissen. Voor meer informatie over slepen en neerzetten, zie Overzicht van slepen en neerzetten.
Opdrachten
Opdrachten maken invoerafhandeling mogelijk op een meer semantisch niveau dan apparaatinvoer. Opdrachten zijn eenvoudige instructies, zoals Cut
, Copy
, Paste
of Open
. Opdrachten zijn handig voor het centraliseren van uw opdrachtlogica. Dezelfde opdracht kan worden geopend vanuit een Menu, op een ToolBarof via een sneltoets. Opdrachten bieden ook een mechanisme voor het uitschakelen van besturingselementen wanneer de opdracht niet beschikbaar is.
RoutedCommand is de WPF-implementatie van ICommand. Wanneer een RoutedCommand wordt uitgevoerd, worden een PreviewExecuted- en een Executed-gebeurtenis gegenereerd op het commando doelwit, die door de elementstructuur tunnelen en bellen, net zoals andere invoer. Als een opdrachtdoel niet is ingesteld, is het element met toetsenbordfocus het opdrachtdoel. De logica waarmee de opdracht wordt uitgevoerd, wordt gekoppeld aan een CommandBinding. Wanneer een Executed gebeurtenis een CommandBinding voor die specifieke opdracht bereikt, wordt de ExecutedRoutedEventHandler op de CommandBinding aangeroepen. Deze handler voert de actie van de opdracht uit.
Voor meer informatie over het aansturen, zie Commando-overzicht.
WPF biedt een bibliotheek met algemene opdrachten die bestaat uit ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommandsen EditingCommands, of u kunt uw eigen opdrachten definiëren.
In het volgende voorbeeld ziet u hoe u een MenuItem instelt, zodat wanneer erop wordt geklikt, de opdracht Paste op de TextBoxwordt aangeroepen, ervan uitgaande dat de TextBox de toetsenbordfocus heeft.
<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
Zie Commanding Overviewvoor meer informatie over opdrachten in WPF.
Het invoersysteem en de basiselementen
Invoergebeurtenissen zoals de gekoppelde gebeurtenissen die zijn gedefinieerd door de Mouse, Keyboarden Stylus klassen worden gegenereerd door het invoersysteem en worden geïnjecteerd in een bepaalde positie in het objectmodel op basis van het testen van de visuele boom tijdens de uitvoeringstijd.
Elk van de gebeurtenissen die Mouse, Keyboarden Stylus definiëren als een gekoppelde gebeurtenis, wordt ook opnieuw weergegeven door de basiselementklassen UIElement en ContentElement als een nieuwe gerouteerde gebeurtenis. De gerouteerde gebeurtenissen van het basiselement worden gegenereerd door klassen die de oorspronkelijke gekoppelde gebeurtenis verwerken en de gebeurtenisgegevens opnieuw gebruiken.
Wanneer de invoergebeurtenis wordt gekoppeld aan een bepaald bronelement via de implementatie van de invoergebeurtenis van het basiselement, kan deze worden gerouteerd via de rest van een gebeurtenisroute die is gebaseerd op een combinatie van logische en visuele structuurobjecten en kan worden verwerkt door toepassingscode. Over het algemeen is het handiger om deze apparaatgerelateerde invoergebeurtenissen af te handelen met behulp van de gerouteerde gebeurtenissen op UIElement en ContentElement, omdat u zowel in XAML als in code meer intuïtieve gebeurtenishandlersyntaxis kunt gebruiken. U kunt ervoor kiezen om de gekoppelde gebeurtenis die in plaats daarvan het proces heeft gestart, af te handelen, maar u zou verschillende problemen ondervinden: de gekoppelde gebeurtenis kan worden gemarkeerd door de verwerking van de basiselementklasse en u moet toegangsmethoden gebruiken in plaats van echte gebeurtenissyntaxis om handlers voor gekoppelde gebeurtenissen te koppelen.
Wat is de volgende stap?
U hebt nu verschillende technieken om invoer in WPF te verwerken. U moet ook een beter begrip hebben van de verschillende typen invoergebeurtenissen en de gerouteerde gebeurtenismechanismen die door WPF worden gebruikt.
Er zijn aanvullende bronnen beschikbaar waarmee WPF-frameworkelementen en gebeurtenisroutering in meer detail worden uitgelegd. Zie de volgende overzichten voor meer informatie, Commanding Overview, Focus Overview, Base Elements Overview, Trees in WPFen Routed Events Overview.
Zie ook
- Overzicht Focus
- Overzicht van opdrachten
- Overzicht van gerouteerde gebeurtenissen
- Overzicht basiselementen
- eigenschappen
.NET Desktop feedback