Översikt över indata
Undersystemet Windows Presentation Foundation (WPF) tillhandahåller ett kraftfullt API för att hämta indata från en mängd olika enheter, inklusive mus, tangentbord, touch och penna. Det här avsnittet beskriver de tjänster som tillhandahålls av WPF och förklarar arkitekturen för indatasystemen.
Indata-API
Den primära indata-API-exponeringen finns i baselementklasserna: UIElement, ContentElement, FrameworkElementoch FrameworkContentElement. Mer information om grundelementen finns i Översikt över baselement. Dessa klasser tillhandahåller funktioner för indatahändelser relaterade till tangenttryckningar, musknappar, mushjul, musrörelse, fokushantering och musfångst, för att nämna några. Genom att placera indata-API:et på baselementen, i stället för att behandla alla indatahändelser som en tjänst, gör indataarkitekturen att indatahändelserna kan hämtas av ett visst objekt i användargränssnittet och stödja ett händelseroutningsschema där fler än ett element har möjlighet att hantera en indatahändelse. Många indatahändelser har ett par associerade händelser. Till exempel är händelsen key down associerad med händelserna KeyDown och PreviewKeyDown. Skillnaden i dessa händelser är hur de dirigeras till målelementet. Förhandsgranskningshändelser passerar elementträdet från rotelementet till målelementet. Bubblande händelser bubblar upp från målelementet till rotelementet. Händelseroutning i WPF beskrivs mer detaljerat senare i den här översikten och i Översikt över routade händelser.
Tangentbords- och musklasser
Förutom indata-API:et för baselementklasserna ger klasserna Keyboard och Mouse ytterligare API för att arbeta med tangentbords- och musindata.
Exempel på indata-API i Keyboard-klassen är egenskapen Modifiers, som returnerar den ModifierKeys som för närvarande trycks in och metoden IsKeyDown, som avgör om en angiven nyckel trycks in.
I följande exempel används metoden GetKeyStates för att avgöra om en Key är i nedläge.
// 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
Exempel på API för inmatning i klassen Mouse är MiddleButton, som hämtar tillståndet för mellanmusknappen, och DirectlyOver, som hämtar elementet som muspekaren för närvarande är över.
I följande exempel avgörs om LeftButton på musen är i Pressed-tillståndet.
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
UpdateSampleResults("Left Button Pressed")
End If
Klasserna Mouse och Keyboard beskrivs mer detaljerat i den här översikten.
Penninmatning
WPF har integrerat stöd för Stylus. Det Stylus är en penninmatning som blev populär genom Tablet PC. WPF-program kan behandla pennan som en mus med hjälp av mus-API:et, men WPF exponerar också en stylusenhetsabstraktion som använder en modell som liknar tangentbordet och musen. Alla stylus-relaterade API:er innehåller ordet "Stylus".
Eftersom pennan kan fungera som en mus kan program som endast stöder musinmatning fortfarande få viss nivå av stöd för pennan automatiskt. När pennan används på ett sådant sätt ges programmet möjlighet att hantera lämplig pennahändelse och hanterar sedan motsvarande mushändelse. Dessutom är tjänster på högre nivå, till exempel bläckinmatning, också tillgängliga via abstraktion för stylusenheten. Mer information om bläck som inmatning finns i Komma igång med bläck.
Händelsehantering
En FrameworkElement kan innehålla andra element som del av sin innehållsmodell och bilda ett elementträd. I WPF kan det överordnade elementet delta i indata som riktas till dess underordnade element eller andra ättlingar genom att hantera händelser. Detta är särskilt användbart för att skapa kontroller av mindre kontroller, en process som kallas "kontrollkomposition" eller "compositing". Mer information om elementträd och hur elementträd relaterar till händelsevägar finns i Trees in WPF.
Händelseroutning är processen att vidarebefordra händelser till flera element, så att ett visst objekt eller element längs vägen kan välja att ge ett betydande svar (genom hantering) på en händelse som kan ha initierats av ett annat element. Routade händelser använder en av tre routningsmetoder: direkt, bubblande överföring och tunneltrafik. Vid direkt routning är källelementet det enda element som meddelas och händelsen dirigeras inte till andra element. Den direktroutade händelsen erbjuder dock fortfarande ytterligare funktioner som endast finns för routade händelser i stället för standard-CLR-händelser. Bubbling fungerar i elementträdet genom att först meddela elementet som genererade händelsen, sedan föräldraelementet och så vidare. Tunneling börjar vid roten av elementträdet och arbetar sig neråt och slutar med det ursprungliga källelementet. Mer information om routade händelser finns i Översikt över routade händelser.
WPF-indatahändelser finns vanligtvis i par som består av en tunnelhändelse och en bubblande händelse. Tunnelhändelser skiljer sig från bubblande händelser med prefixet "Förhandsversion". Till exempel är PreviewMouseMove tunnelversionen av en musflytthändelse och MouseMove är den bubblande versionen av den här händelsen. Den här händelseparkopplingen är en konvention som implementeras på elementnivå och inte är en inbyggd funktion i WPF-händelsesystemet. Mer information finns i avsnittet WPF-indatahändelser i Översikt över routade händelser.
Hantera indatahändelser
Om du vill ta emot indata för ett element måste en händelsehanterare associeras med den specifika händelsen. I XAML är detta enkelt: du refererar till namnet på händelsen som ett attribut för det element som lyssnar efter den här händelsen. Sedan anger du värdet för attributet till namnet på den händelsehanterare som du definierar, baserat på ett ombud. Händelsehanteraren måste vara skriven i kod som C# och kan ingå i en kod bakom fil.
Tangentbordshändelser inträffar när operativsystemet rapporterar viktiga åtgärder som inträffar när tangentbordsfokus ligger på ett element. Mus- och pennahändelser delas in i två kategorier: händelser som rapporterar ändringar i pekarposition i förhållande till elementet och händelser som rapporterar ändringar i enhetsknapparnas tillstånd.
Exempel på tangentbordsinmatningshändelse
I följande exempel lyssnar exemplet efter ett tryck på vänsterpilen. En StackPanel skapas som har en Button. En händelsehanterare som lyssnar efter vänster piltangenttryck är kopplad till Button-instansen.
Det första avsnittet i exemplet skapar StackPanel och Button och kopplar händelsehanteraren för 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
Det andra avsnittet skrivs i kod och definierar händelsehanteraren. När vänsterpilen trycks ned, och Button har tangentbordsfokus, körs hanteraren och färgen på Button ändras till Background. Om tangenten trycks ned, men det inte är vänsterpilen, ändras Background färgen på Button tillbaka till startfärgen.
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
Exempel på musinmatningshändelse
I följande exempel ändras Background-färgen hos en Button när muspekaren kommer in i Button. Färgen Background återställs när musen lämnar Button.
Det första avsnittet i exemplet skapar StackPanel och Button-kontrollen och kopplar händelsehanterarna för MouseEnter- och MouseLeave-händelserna till 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
Det andra avsnittet i exemplet är skrivet i kod och definierar händelsehanterarna. När musen kommer in i Buttonändras Background färg för Button till SlateGray. När musen lämnar Buttonändras Background färgen på Button tillbaka till 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
Textinmatning
Med händelsen TextInput kan du lyssna efter textindata på ett enhetsoberoende sätt. Tangentbordet är det primära sättet att mata in text, men tal, handskrift och andra indataenheter kan också generera textinmatning.
För tangentbordsindata skickar WPF först lämpliga KeyDown/KeyUp händelser. Om dessa händelser inte hanteras och nyckeln är textbaserad (i stället för en kontrollnyckel, till exempel riktningspilar eller funktionsnycklar), utlöses en TextInput händelse. Det finns inte alltid en enkel en-till-en-mappning mellan KeyDown/KeyUp och TextInput händelser eftersom flera tangenttryckningar kan generera ett enda tecken med textinmatning och enkla tangenttryckningar kan generera strängar med flera tecken. Detta gäller särskilt för språk som kinesiska, japanska och koreanska som använder Indatametodredigerare (IME) för att generera tusentals möjliga tecken i motsvarande alfabet.
När WPF skickar en KeyUp/KeyDown händelse ställs Key in på Key.System om tangenttryckningarna kan bli en del av en TextInput händelse (om ALT+S till exempel trycks ned). Detta gör att kod i en KeyDown-händelsehanterare kan kolla efter Key.System och, om den hittas, överlämna bearbetningen till hanteraren för den efterföljande TextInput-händelsen. I dessa fall kan de olika egenskaperna för argumentet TextCompositionEventArgs användas för att fastställa de ursprungliga tangenttryckningarna. Om en IME är aktiv har Key värdet Key.ImeProcessedoch ImeProcessedKey ger den ursprungliga tangenttryckningen eller tangenttryckningarna.
I följande exempel definieras en hanterare för händelsen Click och en hanterare för händelsen KeyDown.
Det första segmentet med kod eller markering skapar användargränssnittet.
<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
Det andra kodsegmentet innehåller händelsehanterarna.
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
Eftersom indatahändelser bubblar upp händelsevägen tar StackPanel emot indata oavsett vilket element som har tangentbordsfokus.
TextBox-kontrollen meddelas först och OnTextInputKeyDown
-hanteraren anropas endast om TextBox inte hanterade indata. Om den PreviewKeyDown händelsen används i stället för händelsen KeyDown anropas OnTextInputKeyDown
-hanteraren först.
I det här exemplet skrivs hanteringslogik två gånger – en gång för CTRL+O och igen för knappens klickhändelse. Detta kan förenklas med hjälp av kommandon i stället för att hantera indatahändelserna direkt. Kommandon beskrivs i den här översikten och i Kommandoöversikt.
Pek- och manipulering
Ny maskinvara och APIer i Windows 7-operativsystemet ger applikationer möjlighet att ta emot indata från flera beröringar samtidigt. WPF gör det möjligt för program att identifiera och svara på beröring på ett sätt som liknar att svara på andra indata, till exempel musen eller tangentbordet, genom att höja händelser när beröring inträffar.
WPF exponerar två typer av händelser när beröring inträffar: pekhändelser och manipulationshändelser. Touch-händelser ger rådata om varje finger på en pekskärm och dess rörelse. Manipulationshändelser tolkar indata som vissa åtgärder. Båda typerna av händelser beskrivs i det här avsnittet.
Förutsättningar
Du behöver följande komponenter för att utveckla ett program som svarar på beröring.
Visual Studio 2010.
Windows 7.
En enhet, till exempel en pekskärm, som stöder Windows Touch.
Terminologi
Följande termer används när touch diskuteras.
Touch är en typ av användarindata som känns igen av Windows 7. Vanligtvis initieras touch genom att sätta fingrarna på en beröringskänslig skärm. Observera att enheter som en pekplatta som är vanlig på bärbara datorer inte stöder touch om enheten bara konverterar fingrets position och rörelse som musinmatning.
Multitouch är touch som sker från mer än en punkt samtidigt. Windows 7 och WPF stöder multitouch. När touch diskuteras i dokumentationen för WPF gäller begreppen för multitouch.
En manipulering inträffar när touch tolkas som en fysisk åtgärd som tillämpas på ett objekt. I WPF tolkar manipuleringshändelser indata som översättning, expansion eller rotationsmanipulering.
En
touch device
representerar en enhet som genererar pekindata, till exempel ett enda finger på en pekskärm.
Kontroller som svarar på touch
Följande kontroller kan rullas genom att dra ett finger över kontrollen om den har innehåll som rullas ur vyn.
ScrollViewer definierar den ScrollViewer.PanningMode anslutna egenskapen som gör att du kan ange om pekpanorering ska aktiveras vågrätt, lodrätt, båda eller ingetdera. Egenskapen ScrollViewer.PanningDeceleration anger hur snabbt rullningen saktar ner när användaren lyfter fingret från pekskärmen. Egenskapen ScrollViewer.PanningRatio bifogad anger förhållandet mellan rullningsförskjutning och översättning av manipulationsförskjutning.
Touch-händelser
Basklasserna, UIElement, UIElement3Doch ContentElement, definierar händelser som du kan prenumerera på så att ditt program svarar på touch. Touch-händelser är användbara när ditt program tolkar touch som något annat än att manipulera ett objekt. Till exempel skulle ett program som gör det möjligt för en användare att rita med en eller flera fingrar prenumerera på touchhändelser.
Alla tre klasserna definierar följande händelser, som fungerar på samma sätt, oavsett vilken klass som definieras.
Precis som tangentbords- och mushändelser är touchhändelserna dirigerade händelser. Händelser som börjar med Preview
är tunnelhändelser och händelser som börjar med Touch
är bubblande händelser. Mer information om routade händelser finns i Översikt över routade händelser. När du hanterar dessa händelser kan du hämta positionen för indata i förhållande till alla element genom att anropa metoden GetTouchPoint eller GetIntermediateTouchPoints.
För att förstå interaktionen mellan touchhändelserna bör du överväga scenariot där en användare sätter ett finger på ett element, flyttar fingret i elementet och sedan lyfter fingret från elementet. Följande illustration visar hur bubblande händelser utförs (tunnelhändelser utelämnas för enkelhet).
Touchhändelser
I följande lista beskrivs sekvensen av händelserna i föregående bild.
Händelsen TouchEnter inträffar en gång när användaren sätter ett finger på elementet.
Händelsen TouchDown inträffar en gång.
Händelsen TouchMove inträffar flera gånger när användaren flyttar fingret i elementet.
Händelsen TouchUp inträffar en gång när användaren lyfter fingret från elementet.
Händelsen TouchLeave inträffar en gång.
När fler än två fingrar används inträffar händelserna för varje finger.
Manipulationshändelser
I fall där ett program gör det möjligt för en användare att manipulera ett objekt definierar klassen UIElement manipulationshändelser. Till skillnad från de beröringshändelser som bara rapporterar pekpositionen rapporterar manipulationshändelserna hur indata kan tolkas. Det finns tre typer av manipuleringar, översättning, expansion och rotation. I följande lista beskrivs hur du anropar de tre typerna av manipuleringar.
Sätt ett finger på ett objekt och flytta fingret över pekskärmen för att anropa en översättningsmanipulering. Detta flyttar vanligtvis objektet.
Sätt två fingrar på ett objekt och flytta fingrarna närmare varandra eller längre ifrån varandra för att anropa en expansionsmanipulation. Detta ändrar vanligtvis storlek på objektet.
Placera två fingrar på ett objekt och rotera fingrarna runt varandra för att anropa en rotationsmanipulering. Detta roterar vanligtvis objektet.
Mer än en typ av manipulering kan ske samtidigt.
När du får objekt att svara på manipuleringar kan du låta objektet verka trögt. Detta kan göra att dina objekt simulerar den fysiska världen. Till exempel, när du knuffar en bok över ett bord, om du trycker tillräckligt hårt, kommer boken att fortsätta röra sig efter att du släppt den. MED WPF kan du simulera det här beteendet genom att skapa manipulationshändelser när användarens fingrar släpper objektet.
Information om hur du skapar ett program som gör det möjligt för användaren att flytta, ändra storlek på och rotera ett objekt finns i Genomgång: Skapa ditt First Touch-program.
UIElement definierar följande manipulationshändelser.
Som standard tar en UIElement inte emot dessa manipulationshändelser. Om du vill ta emot manipulationshändelser på en UIElementanger du UIElement.IsManipulationEnabled till true
.
Körningssökvägen för manipulationshändelser
Tänk dig ett scenario där en användare "kastar" ett objekt. Användaren sätter ett finger på objektet, flyttar fingret över pekskärmen en kort bit och lyfter sedan fingret medan det rör sig. Resultatet av detta är att objektet flyttas under användarens finger och fortsätter att röra sig när användaren lyfter fingret.
Följande illustration visar körningsflödet för manipulationshändelser och viktig information om varje händelse.
Manipulationshändelser
I följande lista beskrivs sekvensen av händelserna i föregående bild.
Händelsen ManipulationStarting inträffar när användaren placerar ett finger på objektet. Med den här händelsen kan du bland annat ange egenskapen ManipulationContainer. I efterföljande händelser kommer positionen för manipuleringen att vara relativ till ManipulationContainer. I andra händelser än ManipulationStartingär den här egenskapen skrivskyddad, så händelsen ManipulationStarting är den enda gången som du kan ange den här egenskapen.
Den ManipulationStarted händelsen inträffar härnäst. Den här händelsen rapporterar ursprunget till manipulationen.
Händelsen ManipulationDelta inträffar flera gånger när en användares fingrar rör sig på en pekskärm. Egenskapen DeltaManipulation för klassen ManipulationDeltaEventArgs rapporterar om manipuleringen tolkas som rörelse, expansion eller översättning. Det är här du utför det mesta av arbetet med att manipulera ett objekt.
Händelsen ManipulationInertiaStarting inträffar när användarens fingrar förlorar kontakten med objektet. Med den här händelsen kan du ange inbromsningen av manipulationerna under tröghet. Det här är så att objektet kan emulera olika fysiska utrymmen eller attribut om du vill. Anta till exempel att ditt program har två objekt som representerar objekt i den fysiska världen och att det ena är tyngre än det andra. Du kan göra så att det tyngre objektet bromsar in snabbare än det lättare objektet.
Den ManipulationDelta händelsen inträffar flera gånger när tröghet inträffar. Observera att den här händelsen inträffar när användarens fingrar rör sig över pekskärmen och när WPF simulerar tröghet. Med andra ord inträffar ManipulationDelta före och efter händelsen ManipulationInertiaStarting. Egenskapen ManipulationDeltaEventArgs.IsInertial rapporterar om den ManipulationDelta händelsen inträffar under tröghet, så att du kan kontrollera den egenskapen och utföra olika åtgärder, beroende på dess värde.
Den ManipulationCompleted händelsen inträffar när manipuleringen och eventuell tröghet upphör. Det vill säga, när alla ManipulationDelta-händelser inträffar, inträffar ManipulationCompleted-händelsen för att signalera att manipuleringen är klar.
UIElement definierar även händelsen ManipulationBoundaryFeedback. Den här händelsen inträffar när metoden ReportBoundaryFeedback anropas i händelsen ManipulationDelta. Händelsen ManipulationBoundaryFeedback gör det möjligt för program eller komponenter att ge visuell feedback när ett objekt når en gräns. Klassen Window hanterar till exempel händelsen ManipulationBoundaryFeedback så att fönstret flyttas något när dess kant påträffas.
Du kan avbryta manipulationen genom att anropa metoden Cancel för händelseargumenten i alla manipulationshändelser förutom ManipulationBoundaryFeedback händelse. När du anropar Cancelhöjs inte längre manipuleringshändelserna och mushändelser inträffar vid beröring. I följande tabell beskrivs relationen mellan den tidpunkt då manipuleringen avbröts och de mushändelser som inträffar.
Händelsen där Avbryt anropas | Mushändelserna som inträffar för indata som redan har inträffat |
---|---|
ManipulationStarting och ManipulationStarted | Musknapp nedtryckt-händelser. |
ManipulationDelta | Händelser för musknapptryck och musförflyttning. |
ManipulationInertiaStarting och ManipulationCompleted | Mus ned, mus flytta och mus upp händelser. |
Observera att om du anropar Cancel när manipuleringen är trög returnerar metoden false
och indata genererar inte mushändelser.
Relationen mellan touch- och manipuleringshändelser
En UIElement kan alltid ta emot beröringshändelser. När egenskapen IsManipulationEnabled är inställd på true
kan en UIElement ta emot både touch- och manipulationshändelser. Om TouchDown-händelsen inte hanteras (dvs. egenskapen Handled är false
) fångar manipulationslogiken upp touchen till elementet och genererar manipulationshändelser. Om egenskapen Handled är inställd på true
i händelsen TouchDown genereras inte manipulationslogik. Följande bild visar relationen mellan beröringshändelser och manipulationshändelser.
Touch- och manipulationshändelser
I följande lista beskrivs relationen mellan touch- och manipulationshändelserna som visas i föregående bild.
När den första touch-enheten genererar en TouchDown händelse på en UIElementanropar manipulationslogik CaptureTouch-metoden som genererar händelsen GotTouchCapture.
När GotTouchCapture inträffar anropar manipuleringslogik metoden Manipulation.AddManipulator som genererar händelsen ManipulationStarting.
När TouchMove händelser inträffar genererar manipulationslogik de ManipulationDelta händelser som inträffar före ManipulationInertiaStarting händelsen.
När den sista pekenheten på elementet höjer händelsen TouchUp, genererar manipulationslogiken händelsen ManipulationInertiaStarting.
Fokus
Det finns två huvudsakliga begrepp som gäller fokus i WPF: tangentbordsfokus och logiskt fokus.
Tangentbordsfokus
Tangentbordsfokus refererar till elementet som tar emot tangentbordsindata. Det kan bara finnas ett element på hela skrivbordet som har tangentbordsfokus. I WPF har elementet som har tangentbordsfokus IsKeyboardFocused inställt på true
. Den statiska Keyboard-metoden FocusedElement returnerar elementet som för närvarande har tangentbordsfokus.
Tangentbordsfokus kan hämtas genom att tabba till ett element eller genom att klicka med musen på vissa element, till exempel en TextBox. Tangentbordsfokus kan också hämtas programmatiskt med hjälp av metoden Focus i klassen Keyboard. Focus försöker ge det angivna elementets tangentbord fokus. Elementet som returneras av Focus är det element som för närvarande har tangentbordsfokus.
För att ett element ska få tangentbordsfokus måste egenskapen Focusable och egenskaperna för IsVisible anges till sant. Vissa klasser, till exempel Panel, har Focusable inställt på false
som standard. Därför kan du behöva ställa in den här egenskapen på true
om du vill att elementet ska kunna få fokus.
I följande exempel används Focus för att ange tangentbordsfokus på en Button. Den rekommenderade platsen för att ange inledande fokus i ett program finns i Loaded händelsehanterare.
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
Mer information om tangentbordsfokus finns i Översikt över fokus.
Logiskt fokus
Logiskt fokus hänvisar till FocusManager.FocusedElement i ett fokusområde. Det kan finnas flera element som har logiskt fokus i ett program, men det kan bara finnas ett element som har logiskt fokus i ett visst fokusomfång.
Ett fokusomfång är ett containerelement som håller reda på FocusedElement inom dess omfång. När fokus lämnar ett fokusomfång förlorar det fokuserade elementet tangentbordsfokus men behåller logiskt fokus. När fokus återgår till fokusomfånget får det fokuserade elementet tangentbordsfokus. Detta gör att tangentbordsfokus kan ändras mellan flera fokusomfattningar, men försäkrar att det fokuserade elementet inom fokusomfånget förblir det fokuserade elementet när fokus returneras.
Ett element kan omvandlas till ett fokusomfång i XAML (Extensible Application Markup Language) genom att ange den FocusManager kopplade egenskapen IsFocusScope till true
eller i kod genom att ange den anslutna egenskapen med hjälp av metoden SetIsFocusScope.
Följande exempel gör en StackPanel till ett fokuseringsomfång genom att ange den kopplade egenskapen 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)
Klasser i WPF som är fokusomfattningar som standard är Window, Menu, ToolBaroch ContextMenu.
Ett element som har tangentbordsfokus kommer också att ha logiskt fokus för det fokusområde som det tillhör. Därför kommer att sätta fokus på ett element med metoden Focus i klassen Keyboard eller baselementsklasserna att försöka ge elementet både tangentbordsfokus och logiskt fokus.
Om du vill fastställa det fokuserade elementet i ett fokusomfång använder du GetFocusedElement. Om du vill ändra det fokuserade elementet för ett fokusomfång använder du SetFocusedElement.
Mer information om logiskt fokus finns i Översikt över fokus.
Musposition
WPF-indata-API:et ger användbar information om koordinatutrymmen. Koordinat (0,0)
är till exempel den övre vänstra koordinaten, men det övre vänstra av vilket element i trädet? Elementet som är målet för indata? Elementet som du kopplade händelsehanteraren till? Eller något annat? För att undvika förvirring kräver WPF-indata-API:et att du anger referensramen när du arbetar med koordinater som hämtas via musen. Metoden GetPosition returnerar muspekarens koordinat i förhållande till det angivna elementet.
Musfångst
Musenheter har specifikt en modal egenskap som kallas musfångst. Musfångst används för att upprätthålla ett övergångsindatatillstånd när en dra och släpp-åtgärd startas, så att andra åtgärder som involverar muspekarens nominella position på skärmen inte nödvändigtvis inträffar. Under dragningen kan användaren inte klicka utan att avbryta dragningen, vilket gör de flesta förflyttningsmarkeringarna olämpliga medan muskontrollen är kvar hos dragpunkten. Indatasystemet exponerar API:er som kan fastställa musfångsttillstånd, samt API:er som kan tvinga musfångst till ett visst element eller rensa musfångsttillstånd. Mer information om dra och släpp-åtgärder finns i Dra och släpp-översikt.
Kommandon
Kommandon möjliggör indatahantering på en mer semantisk nivå än enhetsindata. Kommandon är enkla direktiv, till exempel Cut
, Copy
, Paste
eller Open
. Kommandon är användbara för att centralisera kommandologiken. Samma kommando kan nås från en Menu, på en ToolBareller via ett kortkommando. Kommandon ger också en mekanism för att inaktivera kontroller när kommandot blir otillgängligt.
RoutedCommand är WPF-implementeringen av ICommand. När en RoutedCommand körs, aktiveras händelserna PreviewExecuted och Executed på kommandomålet, som tunnlar och bubblar igenom elementträdet precis som annan indata. Om ett kommandomål inte har angetts är elementet med tangentbordsfokus kommandomålet. Logiken som utför kommandot är kopplad till en CommandBinding. När en Executed händelse når en CommandBinding för det specifika kommandot anropas ExecutedRoutedEventHandler på CommandBinding. Den här hanteraren utför kommandots åtgärd.
Mer information om kommandon finns i Kommandoöversikt.
WPF innehåller ett bibliotek med vanliga kommandon som består av ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommandsoch EditingCommands, eller så kan du definiera dina egna.
I följande exempel visas hur du konfigurerar en MenuItem så att när den klickas anropas kommandot Paste på TextBox, förutsatt att TextBox har tangentbordsfokus.
<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
Mer information om kommandon i WPF finns i Commanding Overview.
Indatasystemet och baselementen
Indatahändelser som de kopplade händelser som definierats av klasserna Mouse, Keyboardoch Stylus genereras av indatasystemet och matas in i en viss position i objektmodellen baserat på träfftestning av det visuella trädet vid körning.
Var och en av de händelser som Mouse, Keyboardoch Stylus definiera som en bifogad händelse exponeras också igen av baselementklasserna UIElement och ContentElement som en ny dirigerad händelse. Baselementets dirigerade händelser genereras av klasser som hanterar den ursprungliga kopplade händelsen och återanvänder händelsedata.
När indatahändelsen associeras med ett visst källelement via implementeringen av baselementets indatahändelse kan den dirigeras genom resten av en händelseväg som baseras på en kombination av logiska och visuella trädobjekt och hanteras av programkod. I allmänhet är det enklare att hantera dessa enhetsrelaterade indatahändelser med hjälp av de dirigerade händelserna på UIElement och ContentElement, eftersom du kan använda mer intuitiv händelsehanterarsyntax både i XAML och i kod. Du kan välja att hantera den kopplade händelsen som initierade processen i stället, men du skulle stöta på flera problem: den kopplade händelsen kan markeras som hanterad av baselementklasshanteringen och du måste använda åtkomstmetoder i stället för sann händelsesyntax för att koppla hanterare för anslutna händelser.
Vad händer nu?
Nu har du flera tekniker för att hantera indata i WPF. Du bör också ha en bättre förståelse för de olika typerna av indatahändelser och de routade händelsemekanismer som används av WPF.
Ytterligare resurser finns tillgängliga som förklarar WPF-ramverkselement och händelseroutning mer detaljerat. Mer information finns i följande översikter: Översikt över kommandon, Focus Overview, Base Elements Overview, Trees in WPFoch Routed Events Overview.
Se även
- Översikt över fokus
- Övergripande genomgång av kommandon
- Översikt över routade händelser
- Översikt över Grundelement
- Egenskaper
.NET Desktop feedback