Przegląd Dane wejściowe
WPF i wyjaśnia architekturę systemów wejściowych.
Interfejs API danych wejściowych
Podstawowa ekspozycja interfejsu API danych wejściowych znajduje się w klasach elementów podstawowych: UIElement, ContentElement, FrameworkElementi FrameworkContentElement. Aby uzyskać więcej informacji na temat elementów podstawowych, zobacz Omówienie elementów podstawowych. Te klasy zapewniają funkcje zdarzeń wejściowych związanych z naciśnięciami klawiszy, przyciskami myszy, kółkiem myszy, ruchem myszy, zarządzaniem fokusem i przechwytywaniem myszy, aby wymienić kilka. Umieszczając wejściowy interfejs API w elementach podstawowych, zamiast traktować wszystkie zdarzenia wejściowe jako usługę, architektura wejściowa umożliwia generowanie zdarzeń wejściowych przez określony obiekt w interfejsie użytkownika oraz obsługę schematu routingu zdarzeń, w którym więcej niż jeden element ma możliwość obsługi zdarzenia wejściowego. Wiele zdarzeń wejściowych ma skojarzona parę zdarzeń. Na przykład zdarzenie w dół klucza jest skojarzone z zdarzeniami KeyDown i PreviewKeyDown . Różnica w tych zdarzeniach polega na tym, jak są one kierowane do elementu docelowego. Podgląd zdarzeń tuneluje drzewo elementów z elementu głównego do elementu docelowego. Bubbling zdarzeń bąbelkowych w górę z elementu docelowego do elementu głównego. Routing zdarzeń w WPF został omówiony bardziej szczegółowo w dalszej części tego przeglądu i w przeglądzie zdarzeń trasowanych.
Klasy klawiatury i myszy
Oprócz wejściowego interfejsu API w klasach Keyboard elementów podstawowych klasa i Mouse klasy zapewniają dodatkowy interfejs API do pracy z klawiaturą i wprowadzaniem myszy.
Przykłady wejściowego interfejsu API w Keyboard klasie to Modifiers właściwość, która zwraca ModifierKeys aktualnie wciśnięty klawisz, i IsKeyDown metodę, która określa, czy określony klawisz jest naciśnięty.
W poniższym przykładzie użyto GetKeyStates metody , aby określić, czy element Key znajduje się w stanie wyłączenia.
// 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
Przykłady wejściowego interfejsu API w Mouse klasie to MiddleButton, który uzyskuje stan środkowego przycisku myszy i DirectlyOver, który pobiera element, nad którym znajduje się wskaźnik myszy.
Poniższy przykład określa, czy LeftButton wskaźnik myszy znajduje się w Pressed stanie .
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
UpdateSampleResults("Left Button Pressed");
}
If Mouse.LeftButton = MouseButtonState.Pressed Then
UpdateSampleResults("Left Button Pressed")
End If
Klasy Mouse i Keyboard zostały szczegółowo omówione w tym omówieniu.
Wprowadzanie rysików
WPF ma zintegrowaną obsługę systemu Stylus. Jest Stylus to dane wejściowe pióra popularne przez komputer typu Tablet. Aplikacje WPF mogą traktować rysik jako mysz przy użyciu interfejsu API myszy, ale WPF uwidacznia również abstrakcję urządzenia rysika, która używa modelu podobnego do klawiatury i myszy. Wszystkie interfejsy API związane z rysikiem zawierają słowo "Stylus".
Ponieważ rysik może działać jako mysz, aplikacje, które obsługują tylko wprowadzanie myszy, nadal mogą automatycznie uzyskać pewien poziom obsługi rysika. Gdy rysik jest używany w taki sposób, aplikacja ma możliwość obsługi odpowiedniego zdarzenia rysika, a następnie obsługuje odpowiednie zdarzenie myszy. Ponadto usługi wyższego poziomu, takie jak dane wejściowe pisma odwrotowego, są również dostępne za pośrednictwem abstrakcji urządzenia rysika. Aby uzyskać więcej informacji na temat pisma oddyskowego jako danych wejściowych, zobacz Wprowadzenie z atramentem.
Routing zdarzeń
Obiekt FrameworkElement może zawierać inne elementy jako elementy podrzędne w modelu zawartości, tworząc drzewo elementów. W WPF element nadrzędny może uczestniczyć w danych wejściowych skierowanych do jego elementów podrzędnych lub innych elementów podrzędnych przez przekazanie zdarzeń. Jest to szczególnie przydatne w przypadku tworzenia kontrolek z mniejszych kontrolek, procesu znanego jako "kompozycja kontrolna" lub "kompositing". Aby uzyskać więcej informacji o drzewach elementów i sposobie, w jaki drzewa elementów odnoszą się do tras zdarzeń, zobacz Drzewa w WPF.
Routing zdarzeń to proces przekazywania zdarzeń do wielu elementów, dzięki czemu określony obiekt lub element wzdłuż trasy może zdecydować się na oferowanie znaczącej odpowiedzi (poprzez obsługę) zdarzenia, które mogło zostać pozyskane przez inny element. Zdarzenia kierowane używają jednego z trzech mechanizmów routingu: bezpośredniego, bubbling i tunelowania. W routingu bezpośrednim element źródłowy jest jedynym elementem powiadamianym, a zdarzenie nie jest kierowane do żadnych innych elementów. Jednak zdarzenie kierowane bezpośrednio nadal oferuje pewne dodatkowe możliwości, które są obecne tylko dla zdarzeń kierowanych, w przeciwieństwie do standardowych zdarzeń CLR. Bubbling działa w górę drzewa elementów, najpierw powiadamiając element, który pozyskał zdarzenie, a następnie element nadrzędny itd. Tunelowanie rozpoczyna się od katalogu głównego drzewa elementów i działa w dół, kończąc na oryginalnym elemecie źródłowym. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Routed Events Overview (Omówienie zdarzeń trasowanych).
Zdarzenia wejściowe WPF zwykle występują w parach składających się z zdarzenia tunelowania i zdarzenia bubbling. Zdarzenia tunelowania są rozróżniane od zdarzeń bubbling z prefiksem "Wersja zapoznawcza". Na przykład PreviewMouseMove jest to wersja tunelowania zdarzenia przenoszenia myszy i MouseMove jest wersję bubbling tego zdarzenia. To parowanie zdarzeń jest konwencją zaimplementowaną na poziomie elementu i nie jest nieodłączną możliwością systemu zdarzeń WPF. Aby uzyskać szczegółowe informacje, zobacz sekcję Zdarzenia wejściowe WPF w temacie Przegląd zdarzeń trasowanych.
Obsługa zdarzeń wejściowych
Aby odbierać dane wejściowe dla elementu, program obsługi zdarzeń musi być skojarzony z tym konkretnym zdarzeniem. W języku XAML jest to proste: odwołujesz się do nazwy zdarzenia jako atrybutu elementu, który będzie nasłuchiwać tego zdarzenia. Następnie należy ustawić wartość atrybutu na nazwę zdefiniowanego programu obsługi zdarzeń na podstawie delegata. Procedura obsługi zdarzeń musi być napisana w kodzie, takim jak C#, i może być zawarta w pliku za kodem.
Zdarzenia klawiatury występują, gdy system operacyjny zgłasza akcje klawiszy, które występują, gdy fokus klawiatury jest na elemecie. Zdarzenia myszy i rysika dzielą się na dwie kategorie: zdarzenia, które zgłaszają zmiany pozycji wskaźnika względem elementu, oraz zdarzenia, które zgłaszają zmiany stanu przycisków urządzenia.
Przykład zdarzenia wprowadzania klawiatury
Poniższy przykład nasłuchuje naciśnięcia klawisza strzałki w lewo. Zostanie StackPanel utworzony element z elementem Button. Procedura obsługi zdarzeń do nasłuchiwania naciśnięcia klawisza strzałki w lewo jest dołączona do Button wystąpienia.
Pierwsza sekcja przykładu tworzy element StackPanel i Button i dołącza procedurę obsługi zdarzeń dla elementu 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
Druga sekcja jest napisana w kodzie i definiuje procedurę obsługi zdarzeń. Po naciśnięciu klawisza strzałki w lewo i Button fokusie klawiatury program obsługi jest uruchamiany, a Background kolor Button jest zmieniany. Jeśli klawisz jest naciśnięty, ale nie jest to lewy klawisz strzałki, Background kolor obiektu zostanie zmieniony z powrotem na jego kolor Button początkowy.
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
Przykład zdarzenia wprowadzania myszy
W poniższym przykładzie Background kolor elementu Button jest zmieniany, gdy wskaźnik myszy wprowadza wartość Button. Kolor Background jest przywracany, gdy mysz opuszcza element Button.
Pierwsza sekcja przykładu tworzy kontrolkę StackPanelButton i dołącza procedury obsługi zdarzeń dla zdarzeń MouseEnter i MouseLeave do elementu 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
Druga sekcja przykładu jest napisana w kodzie i definiuje procedury obsługi zdarzeń. Gdy mysz wprowadzi Buttonznak , Background kolor obiektu Button zostanie zmieniony na SlateGray. Gdy mysz opuszcza Buttonelement , Background kolor obiektu Button zostanie zmieniony z powrotem na 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
Wprowadzanie tekstu
Zdarzenie TextInput umożliwia nasłuchiwanie wprowadzania tekstu w sposób niezależny od urządzenia. Klawiatura jest podstawowym środkiem wprowadzania tekstu, ale mowę, pismo ręczne i inne urządzenia wejściowe mogą również generować wprowadzanie tekstu.
W przypadku danych wejściowych za pomocą klawiatury WPF najpierw wysyła odpowiednie KeyDown/KeyUp zdarzenia. Jeśli te zdarzenia nie są obsługiwane, a klucz jest tekstowy (a nie klucz sterujący, taki jak strzałki kierunkowe lub klucze funkcji), TextInput jest zgłaszane zdarzenie. Nie zawsze istnieje proste mapowanie jeden do jednego między zdarzeniami KeyDown/KeyUp i TextInput , ponieważ wiele naciśnięć klawiszy może wygenerować pojedynczy znak wprowadzania tekstu, a pojedyncze naciśnięcia klawiszy mogą generować ciągi wieloznakowe. Dotyczy to szczególnie języków, takich jak chiński, japoński i koreański, które używają edytorów metod wejściowych (IME) do generowania tysięcy możliwych znaków w odpowiadających im alfabetach.
Gdy platforma WPF wysyła KeyUp/KeyDown zdarzenie, jest ustawiana na Key.System wartość , Key jeśli na przykład naciśnięcie klawiszy może stać się częścią TextInput zdarzenia (jeśli na przykład naciśnięcie klawiszy ALT+S). Dzięki temu kod w procedurze obsługi zdarzeń KeyDown umożliwia sprawdzenie Key.System i, w przypadku znalezienia, pozostawienie przetwarzania dla procedury obsługi zdarzenia zgłoszonego TextInput później. W takich przypadkach różne właściwości argumentu TextCompositionEventArgs mogą służyć do określania oryginalnych naciśnięć klawiszy. Podobnie, jeśli plik IME jest aktywny, Key ma wartość Key.ImeProcessedi ImeProcessedKey daje oryginalne naciśnięcie klawiszy lub naciśnięcia klawiszy.
W poniższym przykładzie zdefiniowano procedurę obsługi dla Click zdarzenia i procedurę obsługi dla zdarzenia KeyDown .
Pierwszy segment kodu lub znaczników tworzy interfejs użytkownika.
<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
Drugi segment kodu zawiera procedury obsługi zdarzeń.
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
Ponieważ zdarzenia wejściowe są bąbelkowe w górę trasy zdarzeń, StackPanel odbiera dane wejściowe niezależnie od tego, który element ma fokus klawiatury. Kontrolka TextBox jest najpierw powiadamiana, a OnTextInputKeyDown procedura obsługi jest wywoływana tylko wtedy, gdy TextBox nie obsłużyła danych wejściowych. Jeśli zdarzenie PreviewKeyDown jest używane zamiast KeyDown zdarzenia, program obsługi jest wywoływany OnTextInputKeyDown jako pierwszy.
W tym przykładzie logika obsługi jest zapisywana dwa razy — jeden raz dla klawiszy CTRL+O i ponownie dla zdarzenia kliknięcia przycisku. Można to uprościć za pomocą poleceń, zamiast bezpośrednio obsługiwać zdarzenia wejściowe. Polecenia zostały omówione w tym omówieniu i w temacie Commanding Overview (Omówienie poleceń).
Dotyk i manipulowanie
Nowy sprzęt i interfejs API w systemie operacyjnym Windows 7 zapewniają aplikacjom możliwość odbierania danych wejściowych z wielu dotknięcia jednocześnie. Platforma WPF umożliwia aplikacjom wykrywanie i reagowanie na dotyk w sposób podobny do reagowania na inne dane wejściowe, takie jak mysz lub klawiatura, przez wywoływanie zdarzeń w przypadku wystąpienia dotyku.
WPF uwidacznia dwa typy zdarzeń w przypadku wystąpienia dotyku: zdarzenia dotykowe i zdarzenia manipulowania. Zdarzenia dotykowe zapewniają nieprzetworzone dane dotyczące każdego palca na ekranie dotykowym i jego ruchu. Zdarzenia manipulowania interpretują dane wejściowe jako określone akcje. Oba typy zdarzeń zostały omówione w tej sekcji.
Wymagania wstępne
Do opracowania aplikacji reagującej na dotyk potrzebne są następujące składniki.
Visual Studio 2010 r.
Windows 7.
Urządzenie, takie jak ekran dotykowy, obsługujący Windows Touch.
Terminologia
Podczas omawiania dotyku są używane następujące terminy.
Touch to typ danych wejściowych użytkownika rozpoznawanych przez Windows 7. Zazwyczaj dotyk jest inicjowany przez umieszczenie palców na ekranie wrażliwym na dotyk. Należy pamiętać, że urządzenia, takie jak touchpad, który jest powszechny na komputerach przenośnych, nie obsługują dotyku, jeśli urządzenie tylko konwertuje położenie i ruch palca jako wejście myszy.
Multitouch to dotyk, który występuje jednocześnie z więcej niż jednego punktu. Windows 7 i WPF obsługują funkcję multitouch. Za każdym razem, gdy dotyk jest omówiony w dokumentacji WPF, koncepcje mają zastosowanie do multitouch.
Manipulacja występuje, gdy dotyk jest interpretowany jako akcja fizyczna, która jest stosowana do obiektu. W WPF zdarzenia manipulowania interpretują dane wejściowe jako translacja, rozszerzanie lub manipulowanie rotacją.
Obiekt
touch devicereprezentuje urządzenie, które produkuje wejście dotykowe, takie jak pojedynczy palec na ekranie dotykowym.
Kontrolki reagujące na dotyk
Poniższe kontrolki można przewijać, przeciągając palcem przez kontrolkę, jeśli zawiera zawartość przewiniętą z widoku.
Element ScrollViewer definiuje dołączoną ScrollViewer.PanningMode właściwość, która umożliwia określenie, czy przesuwanie dotykowe jest włączone w poziomie, w pionie, zarówno, jak i w żadnym z nich. Właściwość ScrollViewer.PanningDeceleration określa, jak szybko przewijanie spowalnia, gdy użytkownik podnosi palec z ekranu dotykowego. Dołączona ScrollViewer.PanningRatio właściwość określa stosunek przesunięcia przewijania do przesunięcia manipulowania translacji.
Zdarzenia dotykowe
Klasy bazowe , UIElement, UIElement3Di ContentElementdefiniują zdarzenia, które można subskrybować, aby aplikacja reagowała na dotyk. Zdarzenia dotykowe są przydatne, gdy aplikacja interpretuje dotyk jako coś innego niż manipulowanie obiektem. Na przykład aplikacja, która umożliwia użytkownikowi rysowanie za pomocą jednego lub kilku palców, subskrybuje zdarzenia dotykowe.
Wszystkie trzy klasy definiują następujące zdarzenia, które zachowują się podobnie, niezależnie od klasy definiującej.
Podobnie jak zdarzenia klawiatury i myszy, zdarzenia dotykowe są kierowane zdarzenia. Zdarzenia rozpoczynające się od Preview są zdarzeniami tunelowania, a zdarzenia rozpoczynające się od Touch są zdarzeniami bubbling. Aby uzyskać więcej informacji na temat zdarzeń kierowanych, zobacz Routed Events Overview (Omówienie zdarzeń trasowanych). Podczas obsługi tych zdarzeń można uzyskać pozycję danych wejściowych względem dowolnego elementu, wywołując metodę GetTouchPoint or GetIntermediateTouchPoints .
Aby zrozumieć interakcję między zdarzeniami dotykowymi, rozważ scenariusz, w którym użytkownik umieszcza jeden palec na elemecie, porusza palcem w elemecie, a następnie podnosi palec z elementu. Na poniższej ilustracji przedstawiono wykonywanie zdarzeń bubbling (zdarzenia tunelowania są pomijane dla uproszczenia).
Zdarzenia dotykowe
Poniższa lista zawiera opis sekwencji zdarzeń na poprzedniej ilustracji.
Zdarzenie TouchEnter występuje jednorazowo, gdy użytkownik umieszcza palec na elemecie .
Zdarzenie TouchDown występuje jednorazowo.
Zdarzenie TouchMove występuje wiele razy, gdy użytkownik przesuwa palec w elemecie .
Zdarzenie TouchUp występuje jeden raz, gdy użytkownik podnosi palec z elementu.
Zdarzenie TouchLeave występuje jednorazowo.
Gdy używane są więcej niż dwa palce, zdarzenia występują dla każdego palca.
Zdarzenia manipulowania
W przypadkach, gdy aplikacja umożliwia użytkownikowi manipulowanie obiektem, UIElement klasa definiuje zdarzenia manipulacji. W przeciwieństwie do zdarzeń dotykowych, które po prostu raportują położenie dotyku, zdarzenia manipulacji raportują, jak można interpretować dane wejściowe. Istnieją trzy typy manipulacji, tłumaczenia, rozszerzania i rotacji. Na poniższej liście opisano sposób wywoływania trzech typów manipulacji.
Umieść palec na obiekcie i przesuń palcem przez ekran dotykowy, aby wywołać manipulację tłumaczenia. Zwykle powoduje to przeniesienie obiektu.
Umieść dwa palce na obiekcie i przesuń palce bliżej lub dalej od siebie, aby wywołać manipulację ekspansją. Zwykle zmienia to rozmiar obiektu.
Umieść dwa palce na obiekcie i obróć palce wokół siebie, aby wywołać manipulację rotacją. Zwykle obraca to obiekt.
Może wystąpić jednocześnie więcej niż jeden typ manipulacji.
Gdy obiekty reagują na manipulacje, obiekt może wydawać się niewładny. Dzięki temu obiekty mogą symulować świat fizyczny. Na przykład, gdy wypchniesz książkę do stołu, jeśli wypchniesz wystarczająco mocno, książka będzie nadal poruszać się po jej wydaniu. Platforma WPF umożliwia symulowanie tego zachowania przez podniesienie zdarzeń manipulacji po wypuści obiekt przez palce użytkownika.
Aby uzyskać informacje o sposobie tworzenia aplikacji, która umożliwia użytkownikowi przenoszenie, zmienianie rozmiaru i obracanie obiektu, zobacz Przewodnik: tworzenie pierwszej aplikacji dotykowej.
Element UIElement definiuje następujące zdarzenia manipulowania.
Domyślnie element UIElement nie odbiera tych zdarzeń manipulowania. Aby odbierać zdarzenia manipulacji w obiekcie UIElement, ustaw wartość UIElement.IsManipulationEnabledtrue.
Ścieżka wykonywania zdarzeń manipulowania
Rozważmy scenariusz, w którym użytkownik "zgłasza" obiekt. Użytkownik umieszcza palec na obiekcie, porusza palcem przez ekran dotykowy na krótką odległość, a następnie podnosi palec, gdy porusza się. W wyniku tego jest to, że obiekt zostanie przeniesiony pod palec użytkownika i będzie nadal poruszać się po użytkowniku podnosi palec.
Poniższa ilustracja przedstawia ścieżkę wykonywania zdarzeń manipulowania i ważne informacje o każdym zdarzeniu.
Zdarzenia manipulowania
Poniższa lista zawiera opis sekwencji zdarzeń na poprzedniej ilustracji.
Zdarzenie ManipulationStarting występuje, gdy użytkownik umieszcza palec na obiekcie. Między innymi to zdarzenie umożliwia ustawienie ManipulationContainer właściwości . W kolejnych zdarzeniach pozycja manipulacji będzie względna względem elementu ManipulationContainer. W przypadku zdarzeń innych niż ManipulationStartingta właściwość jest tylko do odczytu, więc ManipulationStarting zdarzenie jest jedynym momentem, w którym można ustawić tę właściwość.
Zdarzenie następuje ManipulationStarted dalej. To zdarzenie zgłasza pochodzenie manipulacji.
Zdarzenie ManipulationDelta występuje wielokrotnie, gdy palce użytkownika poruszają się na ekranie dotykowym. Właściwość DeltaManipulationManipulationDeltaEventArgs klasy zgłasza, czy manipulowanie jest interpretowane jako przenoszenie, rozszerzanie lub tłumaczenie. W tym miejscu wykonujesz większość zadań manipulowania obiektem.
Zdarzenie ManipulationInertiaStarting występuje, gdy palce użytkownika tracą kontakt z obiektem. To zdarzenie umożliwia określenie opóźnienia manipulacji podczas inercji. Jest to tak, aby obiekt mógł emulować różne przestrzenie fizyczne lub atrybuty, jeśli wybierzesz. Załóżmy na przykład, że aplikacja ma dwa obiekty reprezentujące elementy w świecie fizycznym, a jeden jest cięższy niż drugi. Można sprawić, że cięższy obiekt zwolni szybciej niż lżejszy obiekt.
Zdarzenie ManipulationDelta występuje wiele razy w miarę inercji. Należy pamiętać, że to zdarzenie występuje, gdy palce użytkownika poruszają się po ekranie dotykowym i gdy WPF symuluje bezwładność. Innymi słowy, ManipulationDelta występuje przed i po zdarzeniu ManipulationInertiaStarting . Właściwość ManipulationDeltaEventArgs.IsInertial zgłasza, czy ManipulationDelta zdarzenie występuje podczas inercji, aby można było sprawdzić tę właściwość i wykonać różne akcje w zależności od jego wartości.
Zdarzenie ManipulationCompleted występuje, gdy manipulowanie i wszelkie inercja kończy się. Oznacza to, ManipulationCompleted że po wystąpieniu wszystkich zdarzeń ManipulationDelta zdarzenie następuje, aby zasygnalizować, że manipulowanie zostało zakończone.
Element UIElement definiuje ManipulationBoundaryFeedback również zdarzenie. To zdarzenie występuje, gdy ReportBoundaryFeedback metoda jest wywoływana ManipulationDelta w zdarzeniu. Zdarzenie ManipulationBoundaryFeedback umożliwia aplikacjom lub składnikom przekazywanie wizualnych opinii, gdy obiekt osiąga granicę. Na przykład klasa obsługuje ManipulationBoundaryFeedback zdarzenie, Window aby spowodować, że okno zostanie nieco przeniesione po napotkaniu jego krawędzi.
Manipulowanie można anulować, wywołując metodę Cancel na argumentach zdarzeń w dowolnym zdarzeniu manipulowania z wyjątkiem ManipulationBoundaryFeedback zdarzenia. Wywołanie Cancelmetody powoduje, że zdarzenia manipulowania nie są już wywoływane, a zdarzenia myszy są wykonywane na potrzeby dotyku. W poniższej tabeli opisano relację między czasem anulowania manipulacji a zdarzeniami myszy, które występują.
| Zdarzenie, w ramach którego jest wywoływane anulowanie | Zdarzenia myszy występujące dla danych wejściowych, które już wystąpiły |
|---|---|
| ManipulationStarting i ManipulationStarted | Zdarzenia myszy w dół. |
| ManipulationDelta | Zdarzenia przenoszenia myszy w dół i myszy. |
| ManipulationInertiaStarting i ManipulationCompleted | Zdarzenia myszy w dół, ruch myszą i myszą w górę. |
Należy pamiętać, że jeśli wywołasz Cancel metodę , gdy manipulacja jest niewładna, metoda zwraca wartość false , a dane wejściowe nie zgłaszają zdarzeń myszy.
Relacja między zdarzeniami dotyku i manipulowania
Zawsze UIElement może odbierać zdarzenia dotykowe. Gdy właściwość jest ustawiona IsManipulationEnabled na truewartość , UIElement element może odbierać zdarzenia dotyku i manipulowania. TouchDown Jeśli zdarzenie nie jest obsługiwane (czyli Handled właściwość to false), logika manipulowania przechwytuje dotyk do elementu i generuje zdarzenia manipulowania. Handled Jeśli właściwość jest ustawiona na true wartość w zdarzeniuTouchDown, logika manipulowania nie generuje zdarzeń manipulowania. Na poniższej ilustracji przedstawiono relację między zdarzeniami dotyku i zdarzeniami manipulowania.
Zdarzenia dotyku i manipulowania
Na poniższej liście opisano relację między zdarzeniami dotyku i manipulowania, które są wyświetlane na poprzedniej ilustracji.
Gdy pierwsze urządzenie dotykowe generuje TouchDown zdarzenie na obiekcie UIElement, logika manipulowania wywołuje CaptureTouch metodę, która generuje GotTouchCapture zdarzenie.
W takim GotTouchCapture przypadku logika manipulowania wywołuje metodę Manipulation.AddManipulator , która generuje ManipulationStarting zdarzenie.
Po wystąpieniu zdarzeń TouchMove logika manipulowania generuje ManipulationDelta zdarzenia, które występują przed zdarzeniem ManipulationInertiaStarting .
Gdy ostatnie urządzenie dotykowe na elemecie zgłasza TouchUp zdarzenie, logika manipulowania generuje ManipulationInertiaStarting zdarzenie.
Ukierunkowanie
Istnieją dwa główne pojęcia, które odnoszą się do koncentracji uwagi w WPF: fokus klawiatury i koncentracji uwagi logicznej.
Fokus klawiatury
Fokus klawiatury odnosi się do elementu odbierającego dane wejściowe klawiatury. Na całym pulpicie może znajdować się tylko jeden element, który ma fokus klawiatury. W WPF element, który ma fokus klawiatury, będzie miał IsKeyboardFocused ustawioną wartość true. Metoda FocusedElement statyczna Keyboard zwraca element, który obecnie ma fokus klawiatury.
Fokus klawiatury można uzyskać, tworząc tabulatory do elementu lub klikając myszą na niektórych elementach, takich jak TextBox. Fokus klawiatury można również uzyskać programowo przy użyciu Focus metody w Keyboard klasie . Focus próbuje nadać określonemu elementowi fokus klawiatury. Element zwracany przez Focus jest elementem, który obecnie ma fokus klawiatury.
Aby element uzyskał fokus klawiatury, Focusable właściwość i IsVisible właściwości muszą być ustawione na wartość true. Niektóre klasy, takie jak Panel, mają Focusable domyślnie ustawioną false wartość , dlatego może być konieczne ustawienie tej właściwości na true wartość , jeśli chcesz, aby ten element mógł uzyskać fokus.
W poniższym przykładzie użyto Focus funkcji ustawiania fokusu klawiatury na obiekcie Button. Zalecane miejsce do ustawienia początkowego fokusu w aplikacji znajduje się w procedurze obsługi zdarzeń Loaded .
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
Aby uzyskać więcej informacji na temat fokusu klawiatury, zobacz Omówienie fokusu.
Fokus logiczny
Fokus logiczny odnosi się do FocusManager.FocusedElement zakresu fokusu. Może istnieć wiele elementów, które mają fokus logiczny w aplikacji, ale może istnieć tylko jeden element, który ma fokus logiczny w określonym zakresie fokusu.
Zakres fokusu to element kontenera, który śledzi FocusedElement zakres. Gdy fokus pozostawia zakres fokusu, element fokusu utraci fokus klawiatury, ale zachowa fokus logiczny. Gdy fokus powróci do zakresu fokusu, fokus koncentruje się na fokusie klawiatury. Pozwala to na zmianę fokusu klawiatury między wieloma zakresami fokusu, ale zapewnia, że element fokusu w zakresie fokusu pozostaje elementem skoncentrowanym po powrocie fokusu.
Element można przekształcić w zakres fokusu w języku XAML (Extensible Application Markup Language), ustawiając dołączoną właściwość na truewartość lub w kodzie, ustawiając FocusManager dołączoną właściwość IsFocusScope przy użyciu SetIsFocusScope metody .
Poniższy przykład tworzy StackPanel obiekt w zakresie fokusu, ustawiając dołączoną IsFocusScope właściwość.
<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)
Klasy w WPF, które są domyślnie zakresami fokusu, to Window, Menu, ToolBari ContextMenu.
Element, który ma fokus klawiatury, również będzie miał logiczny fokus dla zakresu fokusu, do którego należy; dlatego ustawienie fokusu Focus na elemecie z metodą w Keyboard klasie lub klasach podstawowych elementów podejmie próbę nadania fokusowi klawiatury elementu i fokusowi logicznemu.
Aby określić element fokusu w zakresie fokusu, użyj polecenia GetFocusedElement. Aby zmienić element fokusu dla zakresu fokusu, użyj polecenia SetFocusedElement.
Aby uzyskać więcej informacji na temat koncentracji uwagi logicznej, zobacz Omówienie koncentracji uwagi.
Położenie myszy
Interfejs API danych wejściowych WPF zawiera przydatne informacje dotyczące przestrzeni współrzędnych. Na przykład współrzędna jest współrzędną (0,0) w lewym górnym rogu, ale lewa górna część tego elementu w drzewie? Element, który jest obiektem docelowym danych wejściowych? Element, do którego dołączono procedurę obsługi zdarzeń? Albo coś innego? Aby uniknąć pomyłek, interfejs API danych wejściowych WPF wymaga określenia ramki odwołania podczas pracy ze współrzędnymi uzyskanymi za pośrednictwem myszy. Metoda GetPosition zwraca współrzędną wskaźnika myszy względem określonego elementu.
Przechwytywanie myszy
Urządzenia myszy w szczególności posiadają modalną cechę znaną jako przechwytywanie myszy. Przechwytywanie myszy służy do zachowania stanu przejściowego wejścia po uruchomieniu operacji przeciągania i upuszczania, dzięki czemu inne operacje obejmujące nominalną pozycję wskaźnika myszy niekoniecznie występują. Podczas przeciągania użytkownik nie może kliknąć bez przerywania przeciągania i upuszczania, co sprawia, że większość wskazówek myszy jest nieodpowiednia, podczas gdy przechwytywanie myszy jest trzymane przez źródło przeciągania. System danych wejściowych uwidacznia interfejsy API, które mogą określać stan przechwytywania myszy, a także interfejsy API, które mogą wymusić przechwytywanie myszy do określonego elementu lub czyścić stan przechwytywania myszy. Aby uzyskać więcej informacji na temat operacji przeciągania i upuszczania, zobacz Przeciąganie i upuszczanie — omówienie.
Polecenia
Polecenia umożliwiają obsługę danych wejściowych na bardziej semantycznym poziomie niż dane wejściowe urządzenia. Polecenia to proste dyrektywy, takie jak Cut, Copy, Pastelub Open. Polecenia są przydatne do scentralizowanie logiki poleceń. Do tego samego polecenia można uzyskać dostęp z elementu Menu, na karcie ToolBarlub za pomocą skrótu klawiaturowego. Polecenia zapewniają również mechanizm wyłączania kontrolek, gdy polecenie stanie się niedostępne.
RoutedCommandto implementacja WPF .ICommand RoutedCommand Po wykonaniu PreviewExecuted elementu zdarzenie i Executed jest wywoływane w obiekcie docelowym polecenia, które tuneluje i bąbelek przez drzewo elementów, podobnie jak inne dane wejściowe. Jeśli element docelowy polecenia nie jest ustawiony, element z fokusem klawiatury będzie elementem docelowym polecenia. Logika wykonująca polecenie jest dołączona do elementu CommandBinding. Gdy Executed zdarzenie osiągnie CommandBinding wartość dla tego konkretnego polecenia, ExecutedRoutedEventHandler wywołana jest wartość on .CommandBinding Ta procedura obsługi wykonuje akcję polecenia.
Aby uzyskać więcej informacji na temat poleceń, zobacz Omówienie poleceń.
WPF udostępnia bibliotekę typowych poleceń, które składają się z ApplicationCommands, MediaCommands, , NavigationCommandsComponentCommandsi EditingCommands, lub można zdefiniować własne.
W poniższym przykładzie pokazano, jak skonfigurować element MenuItem tak, aby po kliknięciu polecenia wywołał Paste polecenie na obiekcie , przy założeniuTextBoxTextBox, że fokus klawiatury.
<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
Aby uzyskać więcej informacji na temat poleceń w WPF, zobacz Commanding Overview (Omówienie poleceń).
System wejściowy i elementy podstawowe
Zdarzenia wejściowe, takie jak dołączone zdarzenia zdefiniowane przez Mouseklasy , Keyboardi Stylus są wywoływane przez system wejściowy i wprowadzane do określonej pozycji w modelu obiektów na podstawie trafienia testowania drzewa wizualnego w czasie wykonywania.
Każde z zdarzeń, które Mouse, Keyboardi Stylus definiują jako dołączone zdarzenie, jest również ponownie uwidocznione przez klasy UIElement elementów podstawowych i ContentElement jako nowe zdarzenie kierowane. Zdarzenia kierowane przez element podstawowy są generowane przez klasy obsługujące oryginalne dołączone zdarzenie i ponownie używając danych zdarzenia.
Gdy zdarzenie wejściowe zostanie skojarzone z określonym elementem źródłowym za pośrednictwem implementacji zdarzeń wejściowych elementu podstawowego, można je kierować przez pozostałą część trasy zdarzenia opartej na kombinacji obiektów logicznego i wizualnego drzewa i być obsługiwane przez kod aplikacji. Ogólnie rzecz biorąc, bardziej wygodne jest obsługę tych zdarzeń wejściowych związanych z urządzeniem przy użyciu zdarzeń kierowanych na UIElement i ContentElement, ponieważ można użyć bardziej intuicyjnej składni programu obsługi zdarzeń zarówno w języku XAML, jak i w kodzie. Możesz zamiast tego obsłużyć dołączone zdarzenie, które zainicjowało proces, ale napotkasz kilka problemów: dołączone zdarzenie może być oznaczone przez obsługę klas elementów bazowych i należy użyć metod dostępu, a nie prawdziwej składni zdarzeń w celu dołączenia procedur obsługi dołączonych zdarzeń.
Co dalej?
Masz teraz kilka technik obsługi danych wejściowych w WPF. Należy również lepiej zrozumieć różne typy zdarzeń wejściowych i mechanizmów zdarzeń kierowanych używanych przez WPF.
Dostępne są dodatkowe zasoby, które szczegółowo wyjaśniają elementy struktury WPF i routing zdarzeń. Zobacz następujące omówienie, aby uzyskać więcej informacji, Omówienie poleceń, Omówienie fokusu, Przegląd elementów podstawowych, Drzewa w WPF i Przegląd zdarzeń trasowanych.