Bemenet áttekintése
A Windows Presentation Foundation (WPF) alrendszer egy hatékony API-t biztosít a különböző eszközökről, például az egérről, a billentyűzetről, az érintésről és a tollról való bevitelhez. Ez a témakör a WPF által nyújtott szolgáltatásokat ismerteti, és ismerteti a bemeneti rendszerek architektúráját.
Bemeneti API
Az elsődleges bemeneti API-kitettség az alapelemosztályokon található: UIElement, ContentElement, FrameworkElementés FrameworkContentElement. További információ az alapelemekről: Alapelemek áttekintése. Ezek az osztályok funkcióval szolgálnak a billentyűnyomókkal, egérgombokkal, egérkerékkel, egérmozgatással, fókuszkezeléssel és egérrögzítéssel kapcsolatos bemeneti eseményekhez, hogy néhányat említsünk. Ha a bemeneti API-t az alapelemekre helyezi, ahelyett, hogy az összes bemeneti eseményt szolgáltatásként kezeli, a bemeneti architektúra lehetővé teszi, hogy a bemeneti eseményeket egy adott objektum forrásként használja a felhasználói felületen, és támogassa az esemény-útválasztási sémát, amely lehetővé teszi, hogy egynél több elem kezelje a bemeneti eseményeket. Számos bemeneti eseményhez tartozik egy eseménypár. A billentyű leütési esemény például a KeyDown és a PreviewKeyDown eseményhez van társítva. Ezekben az eseményekben az a különbség, hogy hogyan irányítják őket a célelemhez. Az előzetes események az elemfán belül a gyökérelemtől a célelemig haladnak lefelé. A buborékos események felfelé terjednek a célelemtől a gyökérelemig. Az esemény-útválasztást a WPF-ben az áttekintés későbbi részében, valamint az irányított események áttekintéseismerteti.
Billentyűzet- és egérosztályok
Az alapelemosztályokon található bemeneti API mellett a Keyboard osztály és Mouse osztályok további API-t biztosítanak a billentyűzet- és egérbemenetek használatához.
Az Keyboard osztály bemeneti API-ja például a Modifiers tulajdonság, amely az aktuálisan lenyomott ModifierKeys ad vissza, valamint a IsKeyDown metódus, amely meghatározza, hogy egy adott kulcs van-e lenyomva.
Az alábbi példa a GetKeyStates metódussal állapítja meg, hogy egy Key lefelé állapotban van-e.
// 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
Az Mouse osztály bemeneti API-jára például MiddleButton, amely a középső egérgomb állapotát szerzi be, és DirectlyOver, amely azt az elemet szerzi be, amely felett az egérmutató éppen van.
Az alábbi példa azt határozza meg, hogy a LeftButton az egéren Pressed állapotban van-e.
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
UpdateSampleResults("Left Button Pressed")
End If
A Mouse és a Keyboard osztályokat részletesebben tárgyaljuk ebben az áttekintésben.
Tollbemenet
A WPF integráltan támogatja a Stylus. A Stylus a Táblagép PC által népszerűvé tett tollbemenet. A WPF-alkalmazások az egér API-val egérként kezelhetik a tollat, de a WPF egy tolleszköz absztrakcióját is elérhetővé teszi, amely a billentyűzethez és az egérhez hasonló modellt használ. Minden tollal kapcsolatos API tartalmazza a "Stylus" szót.
Mivel a toll egérként is használható, a csak az egér bemenetét támogató alkalmazások továbbra is automatikusan megkaphatnak bizonyos szintű tolltámogatást. Ha a tollat ilyen módon használják, az alkalmazás lehetőséget kap a megfelelő tollesemény kezelésére, majd a megfelelő egéresemény kezelésére. Emellett magasabb szintű szolgáltatások, például a tintabemenet, a stylus eszköz absztrakcióján keresztül is elérhetők. További információ a tinta bemenetként való használatáról: lásd Első lépések a tintával.
Eseményútválasztás
A FrameworkElement gyermekelemként más elemeket is tartalmazhat a tartalommodellben, amelyek elemfát alkotnak. A WPF-ben a szülőelem események átadásával részt vehet a gyermekelemekhez vagy más leszármazottakhoz irányított bemenetekben. Ez különösen akkor hasznos, ha kisebb vezérlőkből, úgynevezett "vezérlőösszetételből" vagy "összeállításból" építi ki a vezérlőket. További információ az elemfákról és az elemfák eseményútvonalakhoz való viszonyáról: Fák a WPF.
Az esemény-útválasztás az események több elemhez való továbbításának folyamata, így az útvonal egy adott objektuma vagy eleme dönthet úgy, hogy jelentős választ ad (kezeléssel) egy olyan eseményre, amelyet egy másik elem adott. Az irányított események a három útválasztási mechanizmus egyikét használják: közvetlen, buborékos és bújtatásos. Közvetlen útválasztás esetén a forráselem az egyetlen értesítési elem, és az esemény nem lesz más elemekhez irányítva. A közvetlen útvonalú esemény azonban továbbra is kínál néhány további képességet, amelyek csak az irányított eseményekhez vannak jelen, szemben a szabványos CLR-eseményekkel. A buborékozás az elemfa mentén felfelé haladva működik, először értesítve az elemet, amely az eseményt elindította, majd a szülő elemet, és így tovább. A bújtatás az elemfa gyökerénél kezdődik, és lefelé haladva az eredeti forráselemmel végződik. Az irányított eseményekről további információt Irányított események áttekintésecímű témakörben talál.
A WPF bemeneti eseményei általában olyan párokban jönnek létre, amelyek egy bújtatási eseményből és egy buborékos eseményből állnak. A alagutazási eseményeket az "Előzetes" előtaggal különböztetjük meg a buborékos eseményektől. A PreviewMouseMove például az egérmozgatási esemény alagútba helyezési verziója, a MouseMove pedig az esemény buborékolási verziója. Ez az eseménypárosítás egy olyan konvenció, amely az elem szintjén van implementálva, és nem a WPF-eseményrendszer veleszületett képessége. További részletekért tekintse meg a WPF bemeneti események szakaszát Irányított események áttekintése.
Bemeneti események kezelése
Egy elem bemenetének fogadásához eseménykezelőt kell társítani az adott eseményhez. Az XAML-ben ez egyszerű: az esemény nevére az eseményt figyelő elem attribútumaként hivatkozik. Ezután az attribútum értékét a megadott eseménykezelő nevére állítja egy meghatalmazott alapján. Az eseménykezelőnek olyan kódban kell írnia, mint a C#, és egy kód mögötti fájlban is szerepelhet.
A billentyűzetesemények akkor fordulnak elő, ha az operációs rendszer olyan kulcsfontosságú műveleteket jelent, amelyek akkor fordulnak elő, amikor a billentyűzet fókusza egy elemen van. Az egér- és tollesemények két kategóriába sorolhatók: az egyik az események, amelyek az elemhez viszonyítva a mutató pozíciójának változásait jelentik, a másik pedig az eszközgombok állapotának változásait jelenti.
Példa billentyűzetbemeneti eseményre
Az alábbi példa figyeli a bal nyílbillentyű lenyomását. Létrejön egy StackPanel, amely rendelkezik egy Button. A bal nyílbillentyű lenyomását figyelő eseménykezelő csatlakozik a Button-példányhoz.
A példa első szakasza létrehozza a StackPanel és a Button, és csatolja a KeyDowneseménykezelőt.
<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
A második szakasz kódban van megírva, és meghatározza az eseménykezelőt. Ha a bal nyílbillentyűt lenyomja, és a Button rendelkezik billentyűzetfókusszal, a kezelő lefut, és a Background színe megváltozik a Button-n. Ha le van nyomva a billentyű, de nem a bal nyílbillentyű, a ButtonBackground színe visszaáll az eredeti színére.
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
Példa egérbemeneti eseményre
Az alábbi példában egy ButtonBackground színe megváltozik, amikor az egérmutató beírja a Button. A Background szín akkor lesz visszaállítva, amikor az egér elhagyja a Button.
A példa első szakasza létrehozza a StackPanel és a Button vezérlőt, és csatolja a MouseEnter és MouseLeave események eseménykezelőit a 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
A példa második szakasza kódban van megírva, és meghatározza az eseménykezelőket. Amikor az egér belép a Button, a ButtonBackground színe SlateGraylesz. Amikor az egér elhagyja a Buttonelemet, a ButtonBackground színe visszaáll AliceBlue-ra.
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
Szövegbevitel
Az TextInput esemény lehetővé teszi, hogy eszközfüggetlen módon figyelje a szövegbevitelt. A szövegbevitel elsődleges eszköze a billentyűzet, de a beszéd, a kézírás és más beviteli eszközök is képesek szövegbevitelt generálni.
Billentyűzetbemenet esetén a WPF először elküldi a megfelelő KeyDown/KeyUp eseményeket. Ha ezeket az eseményeket nem kezeli a rendszer, és a kulcs szöveges (nem vezérlőkulcs, például irányított nyilak vagy függvénybillentyűk), akkor a rendszer TextInput eseményt hoz létre. A KeyDown/KeyUp és TextInput események között nem mindig van egyszerű egy-az-egyhez leképezés, mivel több billentyűleütés is létrehozhat egyetlen karaktert a szövegbevitelből, és az egybillentyűs billentyűleütések több karakterből álló sztringeket hozhatnak létre. Ez különösen igaz olyan nyelvekre, mint a kínai, a japán és a koreai, amelyek beviteli módszerszerkesztőket (IMEs) használnak a megfelelő ábécékben szereplő több ezer lehetséges karakter létrehozásához.
Amikor a WPF KeyUp/KeyDown eseményt küld, a KeyKey.System-re van állítva, ha a billentyűleütések egy TextInput esemény részévé válhatnak (például ha az ALT+S billentyűkombinációt lenyomja). Ez lehetővé teszi, hogy a KeyDown eseménykezelő kódja ellenőrizze, hogy van-e Key.System, és ha megtalálja, hagyja a feldolgozást a később létrehozott TextInput esemény kezelőjére. Ezekben az esetekben a TextCompositionEventArgs argumentum különböző tulajdonságai használhatók az eredeti billentyűleütések meghatározásához. Hasonlóképpen, ha egy IME aktív, Key értéke Key.ImeProcessed, és ImeProcessedKey az eredeti billentyűleütést vagy billentyűleütéseket adja meg.
Az alábbi példa egy kezelőt határoz meg az Click eseményhez és egy kezelőt a KeyDown eseményhez.
A kód vagy korrektúra első szegmense létrehozza a felhasználói felületet.
<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
A kód második szegmense tartalmazza az eseménykezelőket.
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
Mivel a bemeneti események felfelé terjednek az eseményútvonal mentén, a StackPanel a bemenetet, attól függetlenül fogadja, hogy melyik elemhez tartozik a billentyűzetfókusz. A TextBox vezérlő először értesítést kap, és a OnTextInputKeyDown
kezelő csak akkor lesz meghívva, ha a TextBox nem kezelte a bemenetet. Ha a KeyDown esemény helyett az PreviewKeyDown eseményt használja, a rendszer először a OnTextInputKeyDown
kezelőt hívja meg.
Ebben a példában a kezelési logika kétszer van megírva – egyszer a CTRL+O billentyűkombinációhoz, majd ismét a gomb kattintási eseményéhez. Ez a parancsok használatával egyszerűsíthető a bemeneti események közvetlen kezelése helyett. A parancsokat ebben az áttekintésben és Parancsok áttekintésecímű témakörben tárgyaljuk.
Érintés és manipuláció
A Windows 7 operációs rendszer új hardvere és API-ja lehetővé teszi az alkalmazások számára, hogy egyszerre több érintéssel fogadják a bemenetet. A WPF lehetővé teszi az alkalmazások számára az érintés észlelését és az érintésre való reagálást más bemenetekre, például az egérre vagy a billentyűzetre való reagáláshoz hasonló módon, az érintéses események emelésével.
A WPF kétféle eseményt tesz elérhetővé érintés esetén: érintéses eseményeket és manipulációs eseményeket. Az érintéses események nyers adatokat szolgáltatnak az érintőképernyőn lévő ujjakról és azok mozgásáról. A manipulációs események bizonyos műveletekként értelmezik a bemenetet. Ebben a szakaszban mindkét eseménytípust tárgyaljuk.
Előfeltételek
Az érintésre reagáló alkalmazások fejlesztéséhez a következő összetevőkre van szüksége.
Visual Studio 2010.
Windows 7.
Olyan eszköz, például érintőképernyő, amely támogatja a Windows Touchot.
Terminológia
Az érintés megvitatásakor a következő kifejezések használatosak.
Touch a Windows 7 által felismert felhasználói beviteli típus. Az érintést általában úgy kezdeményezik, hogy érintésérzékeny képernyőre helyezik az ujját. Vegye figyelembe, hogy a laptopokon gyakran használt érintőpárnához hasonló eszközök nem támogatják az érintést, ha az eszköz csupán az ujj helyzetét és mozgását alakítja át egérbemenetként.
Multitouch érintés, amely egyszerre több pontból is előfordul. A Windows 7 és a WPF támogatja a multitouch használatát. Amikor a WPF dokumentációjában szó esik az érintésről, a fogalmak a multitouch-ra vonatkoznak.
A manipulációs akkor fordulnak elő, ha az érintést egy objektumra alkalmazott fizikai műveletként értelmezik. A WPF-ben a manipulációs események fordítási, bővítési vagy forgatási manipulációként értelmezik a bemenetet.
A
touch device
olyan eszközt jelöl, amely érintéses bemenetet hoz létre, például egyetlen ujját az érintőképernyőn.
Érintésre reagáló vezérlők
Az alábbi vezérlők görgethetők úgy, hogy az ujjával végighúzza a vezérlőn, ha van olyan tartalom, ami kigurul a látótérből.
A ScrollViewer határozza meg a ScrollViewer.PanningMode csatolt tulajdonságot, amely lehetővé teszi annak megadását, hogy az érintéses pásztázás engedélyezve van-e vízszintesen, függőlegesen, mindkettőben vagy egyikben sem. A ScrollViewer.PanningDeceleration tulajdonság azt határozza meg, hogy a görgetés milyen gyorsan lelassul, amikor a felhasználó felemeli az ujját az érintőképernyőről. A ScrollViewer.PanningRatio csatolt tulajdonság meghatározza a görgetési eltolás és a manipulációs eltolás közötti arányt.
Érintési események
Az alaposztályok, UIElement, UIElement3Dés ContentElementolyan eseményeket határoznak meg, amelyekre feliratkozhat, hogy az alkalmazás válaszoljon az érintésre. Az érintéses események akkor hasznosak, ha az alkalmazás az érintést nem objektum módosításaként értelmezi. Például egy alkalmazás, amely lehetővé teszi a felhasználó számára, hogy egy vagy több ujjal rajzoljon, előfizetne az érintéses eseményekre.
Mindhárom osztály a következő eseményeket határozza meg, amelyek a definiáló osztálytól függetlenül hasonlóan viselkednek.
A billentyűzet- és egéreseményekhez hasonlóan az érintéses események is irányított események. A Preview
kezdődő események alagutazási események, a Touch
kezdődő események pedig buborékoló események. Az irányított eseményekről további információt Irányított események áttekintésecímű témakörben talál. Az események kezelésekor a bemenet bármely elemhez viszonyított pozícióját a GetTouchPoint vagy GetIntermediateTouchPoints metódus meghívásával szerezheti be.
Az érintéses események közötti interakció megértéséhez vegye figyelembe azt a forgatókönyvet, amikor a felhasználó egy ujját egy elemre helyezi, az ujját az elembe helyezi, majd felemeli az ujját az elemből. Az alábbi ábra a buborékolási események végrehajtását mutatja be (a bújtatási eseményeket az egyszerűség kedvéért kihagyjuk).
Érintéses események
Az alábbi lista az előző ábrán szereplő események sorrendjét ismerteti.
A TouchEnter esemény egyszer fordul elő, amikor a felhasználó ujját az elemre helyezi.
A TouchDown esemény egyszer fordul elő.
A TouchMove esemény többször fordul elő, amikor a felhasználó mozgatja az ujját az elemen belül.
A TouchUp esemény egyszer fordul elő, amikor a felhasználó felemeli az ujját az elemből.
A TouchLeave esemény egyszer fordul elő.
Ha két ujjnál több ujjat használ, az események minden ujjnál bekövetkeznek.
Manipulációs események
Azokban az esetekben, amikor egy alkalmazás lehetővé teszi a felhasználó számára egy objektum kezelését, a UIElement osztály határozza meg a manipulációs eseményeket. Ellentétben az érintés helyzetéről egyszerűen jelentést tevő érintéses eseményekkel, a manipulációs események azt jelentik, hogyan értelmezhető a bemenet. Háromféle manipuláció, fordítás, bővítés és forgatás létezik. Az alábbi lista bemutatja, hogyan hívhatja meg a három típusú manipulációt.
Helyezze az ujját egy objektumra, és mozgassa az ujját az érintőképernyőn a fordítási manipuláció meghívásához. Ez általában áthelyezi az objektumot.
Helyezzen két ujját egy objektumra, és helyezze közelebb egymáshoz vagy távol egymástól az ujjait egy bővítési manipuláció meghívásához. Ez általában átméretezi az objektumot.
Helyezzen két ujját egy objektumra, és forgassa meg az ujjait egymás körül a forgatás elindításához. Ez általában elforgatja az objektumot.
Egyszerre több típusú manipuláció is előfordulhat.
Ha eléri, hogy az objektumok reagáljanak a manipulációkra, az objektum tehetetlennek tűnhet. Így az objektumok szimulálhatják a fizikai világot. Például, ha egy könyvet áttesz az asztalon, és elég erősen tolja, a könyv tovább mozog miután elengedi. A WPF lehetővé teszi, hogy szimulálja ezt a viselkedést azáltal, hogy manipulációs eseményeket emel, miután a felhasználó ujjai felszabadítják az objektumot.
Az objektumok áthelyezését, átméretezését és elforgatását lehetővé tevő alkalmazások létrehozásáról további információt a Útmutató: Az első érintéses alkalmazás létrehozásacímű témakörben talál.
A UIElement a következő manipulációs eseményeket határozza meg.
Alapértelmezés szerint a UIElement nem kapják meg ezeket a manipulációs eseményeket. Ha UIElementszeretne manipulációs eseményeket fogadni, állítsa be UIElement.IsManipulationEnabled-et true
-re.
A manipulációs események végrehajtási útvonala
Fontolja meg azt a forgatókönyvet, amikor egy felhasználó "eldob" egy objektumot. A felhasználó egy ujjal az objektumra helyezi az ujját, kis távolságra mozgatja az ujját az érintőképernyőn, majd mozgatás közben felemeli az ujját. Ennek az az eredménye, hogy az objektum a felhasználó ujja alatt mozog, és tovább mozog, miután a felhasználó felemelte az ujját.
Az alábbi ábrán a manipulációs események végrehajtási útvonala és az egyes eseményekre vonatkozó fontos információk láthatók.
Manipulációs események
Az alábbi lista az előző ábrán szereplő események sorrendjét ismerteti.
A ManipulationStarting esemény akkor következik be, amikor a felhasználó egy ujját az objektumra helyezi. Az esemény többek között lehetővé teszi a ManipulationContainer tulajdonság beállítását. A következő eseményekben a manipuláció pozíciója a ManipulationContainer-hoz képest lesz meghatározva. A ManipulationStartingeseményt leszámítva ez a tulajdonság csak olvasható, ezért a ManipulationStarting esemény az egyetlen alkalom, amikor beállíthatja ezt a tulajdonságot.
A ManipulationStarted esemény következik be. Ez az esemény a manipuláció eredetét jelenti.
A ManipulationDelta esemény többször fordul elő, amikor a felhasználó ujjai egy érintőképernyőn mozognak. A ManipulationDeltaEventArgs osztály DeltaManipulation tulajdonsága jelzi, hogy a manipuláció mozgásként, bővítésként vagy fordításként van-e értelmezve. Itt hajthatja végre az objektumok manipulálásával végzett munka nagy részét.
A ManipulationInertiaStarting esemény akkor következik be, ha a felhasználó ujjai elveszítik a kapcsolatot az objektummal. Ez az esemény lehetővé teszi a manipulációk lassulásának beállítását tehetetlenség közben. Ez azért van, hogy az objektum különböző fizikai tereket vagy attribútumokat emuláljon, ha úgy dönt. Tegyük fel például, hogy az alkalmazás két olyan objektummal rendelkezik, amelyek a fizikai világban lévő elemeket jelölik, és az egyik nehezebb, mint a másik. A nehezebb objektumot gyorsabban lassíthatja, mint a könnyebb objektum.
A ManipulationDelta esemény a tehetetlenség bekövetkezésekor többször fordul elő. Vegye figyelembe, hogy ez az esemény akkor fordul elő, amikor a felhasználó ujjai átmozdulnak az érintőképernyőn, és amikor a WPF tehetetlenségi műveletet szimulál. Más szóval a ManipulationDelta az ManipulationInertiaStarting esemény előtt és után következik be. A ManipulationDeltaEventArgs.IsInertial tulajdonság azt jelenti, hogy a ManipulationDelta esemény a tehetetlenség során következik-e be, így ellenőrizheti a tulajdonságot, és az értékétől függően különböző műveleteket hajthat végre.
A ManipulationCompleted esemény akkor következik be, amikor a manipuláció és a tehetetlenség véget ér. Vagyis az összes ManipulationDelta esemény bekövetkezése után a ManipulationCompleted esemény azt jelzi, hogy a manipuláció befejeződött.
A UIElement az ManipulationBoundaryFeedback eseményt is meghatározza. Ez az esemény akkor fordul elő, ha a ReportBoundaryFeedback metódus meghívása az ManipulationDelta eseményben történik. A ManipulationBoundaryFeedback esemény lehetővé teszi, hogy az alkalmazások vagy összetevők vizuális visszajelzést adjanak, amikor egy objektum eléri a határt. Például a Window osztály kezeli a ManipulationBoundaryFeedback eseményt, ami miatt az ablak kissé elmozdul, amikor az éléhez ér.
A manipuláció megszakításához bármely manipulációs esemény esetén hívja meg az eseményargumentumokon a Cancel metódust, kivéve a ManipulationBoundaryFeedback eseményt. Amikor meghívja Cancel, a program nem emeli ki a manipulációs eseményeket, és az egéresemények érintésre történnek. Az alábbi táblázat a manipuláció megszakítása és az egéresemények közötti kapcsolatot ismerteti.
Az esemény, amelyben a Mégse lehetőség aktiválva van | A már bekövetkezett bemenethez tartozó egéresemények |
---|---|
ManipulationStarting és ManipulationStarted | Egérgomb lenyomása események. |
ManipulationDelta | Egér lenyomás és egér mozgatás események. |
ManipulationInertiaStarting és ManipulationCompleted | Egérlenyomás, egérmozgatás és egérelengedés események. |
Vegye figyelembe, hogy ha a Cancel-t hívja meg, amikor a manipuláció tehetetlenségben van, a metódus false
-et ad vissza, és a bemenet nem vált ki egéreseményeket.
Az érintéses és a manipulációs események közötti kapcsolat
A UIElement mindig fogadhat érintéses eseményeket. Ha a IsManipulationEnabled tulajdonság értéke true
, a UIElement érintéses és manipulációs eseményeket is fogadhatnak. Ha a TouchDown esemény nem kezelhető (vagyis a Handled tulajdonság false
), a manipulációs logika rögzíti az elem érintését, és létrehozza a manipulációs eseményeket. Ha a Handled tulajdonság true
van beállítva az TouchDown eseményben, a manipulációs logika nem hoz létre manipulációs eseményeket. Az alábbi ábra az érintéses események és a manipulációs események közötti kapcsolatot mutatja be.
érintéses és manipulációs események közötti kapcsolat
Az alábbi lista az előző ábrán látható érintéses és manipulációs események közötti kapcsolatot ismerteti.
Amikor az első érintéses eszköz létrehoz egy TouchDown eseményt egy UIElement, a manipulációs logika meghívja a CaptureTouch metódust, amely létrehozza a GotTouchCapture eseményt.
Amikor a GotTouchCapture bekövetkezik, a manipulációs logika meghívja a Manipulation.AddManipulator metódust, amely létrehozza a ManipulationStarting eseményt.
A TouchMove események bekövetkezésekor a manipulációs logika létrehozza a ManipulationInertiaStarting esemény előtti ManipulationDelta eseményeket.
Amikor az elem utolsó érintőeszköze létrehozza a TouchUp eseményt, a manipulációs logika létrehozza a ManipulationInertiaStarting eseményt.
Fókusz
A WPF-ben a fókusznak két fő fogalma van: a billentyűzetfókusz és a logikai fókusz.
Billentyűzetfókusz
A billentyűzetfókusz a billentyűzetbemenetet fogadó elemre vonatkozik. A billentyűzetfókuszt tartalmazó asztalon csak egy elem lehet. A WPF-ben a billentyűzetfókuszú elem IsKeyboardFocusedtrue
lesz beállítva. A statikus Keyboard metódus FocusedElement az aktuális billentyűzetfókuszú elemet adja vissza.
A billentyűzetfókuszt úgy érheti el, hogy egy elemhez lapozza az egérgombot, vagy rákattint bizonyos elemekre, például egy TextBox. A billentyűzetfókusz programozott módon is elérhető a Keyboard osztály Focus metódusával. Focus megpróbálja fókuszba helyezni a megadott elem billentyűzetét. A Focus által visszaadott elem az az elem, amely jelenleg billentyűzetfókuszú.
Ahhoz, hogy egy elem megkapja a billentyűzetfókuszt, a Focusable tulajdonságot és a IsVisible tulajdonságot igaz kell beállítani. Egyes osztályok, mint például a Panel, alapértelmezés szerint úgy vannak beállítva, hogy a Focusable értéke false
legyen; ezért szükség lehet rá, hogy ezt a tulajdonságot true
állítsa, ha azt szeretné, hogy az elem fókuszt kaphasson.
Az alábbi példa a Focus eszközként való használatával állítja be a billentyűzetfókuszt egy Button-n. Az alkalmazás kezdeti fókuszának beállításához ajánlott hely az Loaded eseménykezelőben található.
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
További információ a billentyűzetfókuszról: Fókusz áttekintése.
Logikai fókusz
A logikai fókusz a fókusz hatókörében a FocusManager.FocusedElement-ra utal. Több olyan elem is lehet, amelynek logikai fókusza van egy alkalmazásban, de lehet, hogy csak egy elem rendelkezik logikai fókuszsal egy adott fókusztartományban.
A fókusztartomány egy tárolóelem, amely nyomon követi a saját tartományán belüli FocusedElement-t. Amikor a fókusz elhagyja a fókusz hatókörét, a fókuszált elem elveszíti a billentyűzet fókuszát, de megtartja a logikai fókuszt. Amikor a fókusz visszakerül a fókusz hatókörébe, a szűrt elem megkapja a billentyűzetfókuszt. Ez lehetővé teszi, hogy a billentyűzet fókusza több fókusztartomány között megváltozzon, de biztosítja, hogy a fókusz hatókörében lévő szűrt elem a fókusz visszatérésekor is a szűrt elem maradjon.
Az elemek fókuszhatókörré alakíthatók az Extensible Application Markup Language (XAML) alkalmazásban a FocusManager csatolt tulajdonság IsFocusScopetrue
beállításával, vagy kódban a csatolt tulajdonság SetIsFocusScope metódussal történő beállításával.
Az alábbi példa a StackPanel elemet fókuszterületté alakítja a IsFocusScope csatolt tulajdonság beállításával.
<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)
A WPF-ben alapértelmezés szerint fókuszhatókörként szolgáló osztályok Window, Menu, ToolBarés ContextMenu.
A billentyűzetfókuszú elem logikai fókuszt is kap arra a fókusztartományra, amelyhez tartozik; Ezért a Keyboard osztály vagy az alapelemosztály Focus metódusával az elem fókuszának beállítása megkísérli az elem billentyűzetfókuszát és logikai fókuszt adni.
A fókusz hatókörében lévő fókuszált elem meghatározásához használja a GetFocusedElement. A fókusz hatókör fókuszált elemének módosításához használja a SetFocusedElement.
További információ a logikai fókuszról: Fókusz áttekintése.
Egér helyzete
A WPF bemeneti API hasznos információkat nyújt a koordináta-terekről. A koordináta (0,0)
például a bal felső koordináta, de a fa melyik elemének bal felső része? Az elem, amely a bemeneti cél? Az az elem, amelyhez az eseménykezelőt csatolta? Vagy valami más? A félreértések elkerülése érdekében a WPF bemeneti API-nak meg kell adnia a referenciakeretet, amikor az egérrel kapott koordinátákkal dolgozik. A GetPosition metódus visszaadja az egérmutató koordinátáját a megadott elemhez képest.
Egérrögzítés
Az egéreszközök kifejezetten az egérrögzítésnek nevezett modális jellemzővel rendelkeznek. Az egérrögzítés átmeneti bemeneti állapot fenntartására szolgál a húzási művelet indításakor, így az egérmutató névleges képernyőpozícióját érintő egyéb műveletek nem feltétlenül fordulnak elő. A húzás során a felhasználó nem kattinthat anélkül, hogy megszakítaná a húzást, ami miatt a legtöbb egérrel kapcsolatos visszajelzés nem megfelelő, miközben az egérrögzítést a húzási kiindulópont tartja. A bemeneti rendszer olyan API-kat tesz elérhetővé, amelyek meghatározzák az egérrögzítés állapotát, valamint olyan API-kat, amelyek kényszeríthetik az egér rögzítését egy adott elemre, vagy törölhetik az egérrögzítés állapotát. A húzás és ejtés műveletekről további információt az Húzás és ejtés áttekintésecímű témakörben talál.
Parancsok
A parancsok az eszköz bemeneténél szemantikusabb szinten teszik lehetővé a bemenetek kezelését. A parancsok egyszerű irányelvek, például Cut
, Copy
, Paste
vagy Open
. A parancsok hasznosak a parancslogika központosításához. Ugyanez a parancs egy Menu, egy ToolBarvagy egy billentyűparancs segítségével érhető el. A parancsok azt is lehetővé teszik, hogy letiltsa a vezérlőket, amikor a parancs elérhetetlenné válik.
RoutedCommand a ICommandWPF-implementációja. Egy RoutedCommand végrehajtásakor egy PreviewExecuted és egy Executed esemény jön létre a parancscélon, amely a többi bemenethez hasonlóan az elemfán keresztüli alagúton és buborékon halad át. Ha nincs beállítva parancscél, a billentyűzetfókuszú elem lesz a parancscél. A parancsot végrehajtó logika egy CommandBinding-hoz van csatolva. Amikor egy Executed esemény egy CommandBinding-hez ér az adott parancshoz, a CommandBinding-on elindul a ExecutedRoutedEventHandler. Ez a kezelő végrehajtja a parancs műveletet.
További információ a parancsolásról: Parancsok áttekintése.
A WPF a ApplicationCommands, MediaCommands, ComponentCommands, NavigationCommandsés EditingCommandsálló gyakori parancsok tárát tartalmazza, vagy saját parancsokat is definiálhat.
Az alábbi példa bemutatja, hogyan állíthat be egy MenuItem, hogy kattintáskor meghívja a TextBoxPaste parancsát, feltéve, hogy a TextBox billentyűzetfókuszban van.
<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
További információ a WPF parancsairól: Parancsok áttekintése.
A bemeneti rendszer és az alapelemek
A bemeneti eseményeket, mint például a Mouse, Keyboardés Stylus osztály által meghatározott csatolt eseményeket, a bemeneti rendszer emeli ki és injektálja az objektummodell egy adott helyzetébe, a vizuális fa futásidejű találatesztelése alapján.
Az Mouse, Keyboardés Stylus csatolt eseményként definiált eseményeket az alapelemosztályok UIElement és ContentElement új, irányított eseményként is közzéteheti. Az alapelem által irányított eseményeket az eredeti csatolt eseményt kezelő osztályok generálják, és újra felhasználják az eseményadatokat.
Ha a bemeneti esemény egy adott forráselemhez lesz társítva az alapelem bemeneti esemény implementálásán keresztül, akkor a logikai és vizualizációs faobjektumok kombinációján alapuló eseményútvonalon keresztül irányítható, és alkalmazáskóddal kezelhető. Általában kényelmesebb ezeket az eszközhöz kapcsolódó bemeneti eseményeket a UIElement és a ContentElementirányított eseményekkel kezelni, mert intuitívabb eseménykezelő szintaxist használhat az XAML-ben és a kódban is. Dönthet úgy, hogy a folyamatot kezdeményező csatolt eseményt kezeli, de több problémával is szembe kell néznie: a csatolt eseményt az alapelemosztály kezelése kezelheti, és a csatolt események kezelőinek csatolásához a kiegészítő metódusokat kell használnia a valódi eseményszintaxis helyett.
Mi a következő lépés?
Most már számos módszere van a WPF-ben történő bevitel kezelésére. Emellett jobban ismernie kell a különböző típusú bemeneti eseményeket és a WPF által használt irányított eseménymechanizmusokat.
További források állnak rendelkezésre, amelyek részletesebben ismertetik a WPF-keretrendszer elemeit és az esemény-útválasztást. További információkért tekintse meg a következő áttekintéseket: Parancsok áttekintése, Fókusz áttekintése, Alapelemek áttekintése, Fák a WPF-ben, és Irányított események áttekintése.
Lásd még:
.NET Desktop feedback