Übersicht über Ereignisse und Routingereignisse

Applies to Windows and Windows Phone

Wir beschreiben das Programmierkonzept von Ereignissen in einer Windows-Runtime-App bei Verwendung von C#-, Visual Basic- oder Visual C++-Komponentenerweiterungen als Programmiersprache und XAML für die UI-Definition. Sie können im Rahmen der Deklarationen für UI-Elemente Handler für Ereignisse in XAML zuweisen. Alternativ können Sie Handler im Code hinzufügen. Die Windows-Runtime unterstützt Routingereignisse: Bestimmte Eingabeereignisse und Datenereignisse können von anderen Objekten behandelt werden als dem Objekt, von dem das Ereignis ausgelöst wurde. Routingereignisse sind hilfreich, wenn Sie Steuerelementvorlagen definieren oder Seiten oder Layoutcontainer verwenden.

Ereignisse als Programmierkonzept

Grundsätzlich sind Ereigniskonzepte bei der Programmierung einer Windows-Runtime-App mit dem Ereignismodell in den meisten gängigen Programmiersprachen vergleichbar. Wenn Sie bereits mit .NET- oder C++-Ereignissen vertraut sind, kommen Sie sofort zurecht. Für verschiedene allgemeine Aufgaben, wie das Hinzufügen von Handlern, müssen Sie aber nicht allzu viel über Ereignismodellkonzepte wissen.

Wenn Sie C#, Visual Basic oder C++/CX als Programmiersprache verwenden, wird die UI im Markup (XAML) definiert. Bei der XAML-Markupsyntax ähneln einige der Prinzipien, nach denen UI-Ereignisse aus Markupelementen mit einer Laufzeitcodeentität verbunden werden, denen anderer Webtechnologien (z. B. ASP.NET oder HTML5).

Hinweis  Der Code, der die Laufzeitlogik für eine mit XAML definierte UI bereitstellt, wird häufig CodeBehind oder CodeBehind-Datei genannt. In den Projektmappenansichten von Microsoft Visual Studio wird diese Beziehung grafisch dargestellt. Dabei ist die CodeBehind-Datei eine abhängige und geschachtelte Datei zu der XAML-Seite, auf die sie sich bezieht.

Button.Click: Einführung in Ereignisse und XAML

Zu den häufigsten Programmieraufgaben für eine Windows-Runtime-App gehört es, Benutzereingaben für die UI zu erfassen. So kann Ihre UI beispielsweise eine Schaltfläche enthalten, auf die der Benutzer klicken muss, um Informationen zu senden oder einen Zustand zu ändern.

Sie definieren die UI für Ihre Windows-Runtime-App mittels XAML-Generierung. Bei diesem XAML handelt es sich meist um die Ausgabe einer Designoberfläche in Visual Studio. Sie können das XAML auch in einem Nur-Text-Editor oder in einem XAML-Editor eines Drittanbieters schreiben. Beim Generieren dieses XAML können Sie Ereignishandler für einzelne UI-Elemente verknüpfen, während Sie gleichzeitig alle anderen XAML-Attribute definieren, die Eigenschaftswerte dieses UI-Elements einrichten.

Zur Ereignisverknüpfung in XAML gehört, dass Sie den Namen der Handlermethode, die Sie bereits definiert haben oder später in Ihrem CodeBehind definieren werden, als Zeichenfolge angeben. Dieses XAML definiert beispielsweise ein Button-Objekt mit anderen Eigenschaften (x:Name, Content), die als Attribute zugewiesen sind, und verknüpft einen Handler für das Click-Ereignis durch Verweis auf eine Methode namens showUpdatesButton_Click:


<Button x:Name="showUpdatesButton"
  Content="{Binding ShowUpdatesText}"
  Click="showUpdatesButton_Click"/>

Tipp  Ereignisverknüpfung ist ein Begriff der Programmiersprache. Er bezieht sich auf den Prozess oder Code, mit dem Sie angeben, dass Vorkommen eines Ereignisses eine benannte Handlermethode aufrufen sollen. In den meisten prozeduralen Codemodellen handelt es sich bei der Ereignisverknüpfung um impliziten oder expliziten "AddHandler"-Code, der sowohl das Ereignis als auch die Methode benennt und in der Regel eine Zielobjektinstanz verwendet. In XAML ist "AddHandler" implizit und die Ereignisverknüpfung umfasst nur das Benennen des Ereignisses als Attributnamen eines Objektelement und das Benennen des Handlers als Wert dieses Attributs.

Sie schreiben den eigentlichen Handler in der Programmiersprache, die Sie für Ihren gesamten App-Code oder CodeBehind verwenden. Mit dem Attribut Click="showUpdatesButton_Click" haben Sie einen Vertrag erstellt, mit dem beim Kompilieren des Markups und Analysieren des XAML sowohl der XAML-Markupkompilierschritt in der Erstellungsaktion Ihrer IDE als auch die mögliche XAML-Analyse beim Laden der App eine Methode mit dem Namen showUpdatesButton_Click finden können, die Teil des App-Codes ist. showUpdatesButton_Click muss eine Methode darstellen, die eine kompatible Methodensignatur (basierend auf einem Delegaten) für jeden Handler des Click-Ereignisses implementiert. Dieser Code definiert z. B. denshowUpdatesButton_Click-Handler.


private void showUpdatesButton_Click (object sender, RoutedEventArgs e) {
    Button b = sender as Button;
    //more logic to do here...
}

In diesem Beispiel basiert die showUpdatesButton_Click-Methode auf dem RoutedEventHandler-Delegaten. Sie wissen, dass dies der zu verwendende Delegat ist, weil er in der Syntax für die Click-Methode auf der MSDN-Referenzseite aufgeführt wird.

Tipp  Visual Studio bietet eine bequeme Methode zum Benennen des Ereignishandlers und zum Definieren der Handlermethode während der Bearbeitung von XAML. Wenn Sie den Attributnamen des Ereignisses im XAML-Text-Editor bereitstellen, warten Sie einen Moment, bis eine Microsoft IntelliSense-Liste angezeigt wird. Wenn Sie in der Liste auf <Neuer Ereignishandler> klicken, schlägt Microsoft Visual Studio einen Methodennamen vor, der auf dem x:Name des Elements (oder der Typbezeichnung), dem Ereignisnamen und einem numerischen Suffix basiert. Anschließend können Sie mit der rechten Maustaste auf den ausgewählten Ereignishandler und dann mit der linken Maustaste auf Zum Ereignishandler navigieren klicken. Dadurch navigieren Sie direkt zu der neu eingefügten Ereignishandlerdefinition, wie sie in der Code-Editoransicht Ihrer CodeBehind-Datei für die XAML-Seite angezeigt wird. Der Ereignishandler hat bereits die richtige Signatur, einschließlich des sender-Parameters und der Ereignisdatenklasse, die von dem Ereignis verwendet wird. Wenn zudem bereits eine Handlermethode mit der richtigen Signatur im CodeBehind vorhanden ist, wird der Name dieser Methode zusammen mit der Option <Neuer Ereignishandler> im Auto-Vervollständigen-Dropdown angezeigt. Sie können auch die Tabulatortaste drücken, anstatt auf die IntelliSense-Listenelemente zu klicken.

Definieren eines Ereignishandlers

Für Objekte, die UI-Elemente darstellen und in XAML deklariert werden, wird Ereignishandlercode in der partiellen Klasse definiert, die als CodeBehind für eine XAML-Seite fungiert. Ereignishandler sind Methoden, die Sie als Teil der Ihrem XAML zugeordneten partiellen Klasse schreiben. Diese Ereignishandler basieren auf den Delegaten, die von einem bestimmten Ereignis verwendet werden. Die Ereignishandlermethoden können öffentlich oder privat sein. Der private Zugriff funktioniert, weil der vom XAML erstellte Handler und die Instanz letztendlich durch die Codegenerierung verbunden werden. Im Allgemeinen wird empfohlen, die Ereignishandlermethoden in der Klasse öffentlich zu machen.

Hinweis  Ereignishandler für C++ werden nicht in partiellen Klassen definiert, sondern im Header als private Klassenmember deklariert. Bei den Erstellungsaktionen für ein C++-Projekt wird Code generiert, der das XAML-Typsystem und das CodeBehind-Modell für C++ unterstützt.

Der sender-Parameter und Ereignisdaten

Der Handler, den Sie für das Ereignis schreiben, kann auf zwei Werte zugreifen. Diese Werte sind jedes Mal als Eingabe verfügbar, wenn der Handler aufgerufen wird. Der erste Wert ist sender. Dabei handelt es sich um einen Verweis auf das Objekt, dem der Handler angefügt ist. Der sender-Parameter ist als Object-Basistyp typisiert. Häufig wird sender in einen präziseren Typ umgewandelt. Diese Maßnahme ist nützlich, wenn Sie beabsichtigen, den Zustand direkt für das sender-Objekt zu überprüfen oder zu ändern. Abhängig davon, wo der Handler angefügt wird, und von anderen Designmerkmalen wissen Sie bei Ihrem eigenen App-Design in der Regel, dass es sich um einen Typ handelt, in den sender sicher umgewandelt werden kann.

Den zweiten Wert stellen Ereignisdaten dar. In der Regel sind diese in Syntaxdefinitionen als e-Parameter enthalten. Wenn Sie feststellen möchten, welche Eigenschaften für Ereignisdaten verfügbar sind, prüfen Sie den e-Parameter des Delegaten, der dem behandelten Ereignis zugewiesen ist. Verwenden Sie dann IntelliSense oder den Objektkatalog in Visual Studio. Sie können auch in der Referenzdokumentation von Windows Runtime nachschlagen.

Bei einigen Ereignissen ist die Kenntnis der speziellen Eigenschaftswerte der Ereignisdaten so wichtig wie die Kenntnis, dass das Ereignis eingetreten ist. Das gilt speziell bei Eingabeereignissen. Bei Zeigerereignissen kann die Position des Zeigers beim Auslösen des Ereignisses wichtig sein. Bei Tastaturereignissen wird durch alle möglichen Tastendrücke ein KeyDown- und KeyUp-Ereignis ausgelöst. Um zu bestimmen, welche Taste von einem Benutzer gedrückt wurde, müssen Sie auf die KeyRoutedEventArgs-Klasse zugreifen, die für den Ereignishandler verfügbar ist. Weitere Informationen zur Behandlung von Eingabeereignissen finden Sie unter Reaktion auf Tastatureingaben und Schnellstart: Zeiger. Bei Eingabeereignissen und Eingabeszenarien gibt es häufig weitere Überlegungen, die in diesem Thema nicht behandelt werden, wie das Erfassen des Zeigers bei Zeigerereignissen oder Zusatztasten und Plattformtastencodes für Tastaturereignisse.

Ereignishandler, die das async-Muster verwenden

In einigen Fällen wird die Verwendung von APIs empfohlen, die innerhalb eines Ereignishandlers ein async-Muster verwenden. Beispielsweise können Sie eine Button in einer AppBar verwenden, um eine Dateiauswahl anzuzeigen und mit ihr zu interagieren. Viele der Dateiauswahl-APIs sind jedoch asynchron. Sie müssen innerhalb eines async/Awaitable-Bereichs aufgerufen werden, und dies wird vom Compiler erzwungen. Was Sie tun können, ist Ihrem Ereignishandler das async-Schlüsselwort hinzuzufügen, sodass er jetzt async void ist. Nun kann Ihr Ereignishandler async/Awaitable-Aufrufe durchführen.

Ein Beispiel für die Benutzerinteraktions-Ereignisbehandlung mit dem async-Muster finden Sie unter Dateizugriff und -auswahl (in der Reihe Erstellen Ihrer ersten Windows-Runtime-App mit C# oder Visual Basic). Siehe auch Schnellstart: Abrufen asynchroner APIs in C# oder Visual Basic

Hinzufügen von Ereignishandlern im Code

Es gibt noch andere Möglichkeiten als XAML, um einem Objekt einen Ereignishandler zuzuweisen. Sie können die spezielle Syntax zum Hinzufügen von Ereignishandlern einer Sprache nutzen, um bestimmten Objekten (auch Objekten, die in XAML nicht verwendet werden können) Ereignishandler im Code hinzufügen.

In C# wird für die Syntax der +=-Operator verwendet. Sie registrieren den Handler, indem Sie auf der rechten Seite des Operators auf den Namen der Ereignishandlermethode verweisen.

Wenn Objekten, die in der Laufzeit-UI erscheinen, Ereignishandler per Code hinzugefügt werden, ist es eine übliche Vorgehensweise, diese Handler als Reaktion auf ein Objektlebensdauer-Ereignis oder einen Rückruf hinzuzufügen, wie z. B. Loaded oder OnApplyTemplate. Die Ereignishandler für das relevante Objekt stehen dann zur Laufzeit für Ereignisse bereit, die von Benutzern eingeleitet werden. Dieses Beispiel zeigt eine XAML-Gliederung der Seitenstruktur und führt anschließend die C#-Sprachsyntax für das Hinzufügen eines Ereignishandlers zu einem Objekt auf.


<Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded">
  <StackPanel>
    <TextBlock Name="textBlock1">Put the pointer over this text</TextBlock>
...
  </StackPanel>
</Grid>


void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += textBlock1_PointerEntered;
    textBlock1.PointerExited += textBlock1_PointerExited;
}

Hinweis  Eine ausführlichere Syntax ist vorhanden. 2005 wurde in C# der Rückschluss auf Delegaten als neues Feature eingeführt. Damit kann der Compiler die neue Delegatinstanz ableiten, und die vorherige, einfachere Syntax kann verwendet werden. Die Funktion der ausführlichen Syntax entspricht dem vorherigen Beispiel. Vor der Registrierung wird jedoch explizit eine neue Delegatinstanz erstellt. Der Delegatrückschluss wird somit nicht genutzt. Diese explizite Syntax ist zwar nicht so üblich, aber dennoch in einigen Codebeispielen anzutreffen.


void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += new PointerEventHandler(textBlock1_PointerEntered);
    textBlock1.PointerExited += new MouseEventHandler(textBlock1_PointerExited);
}

Für Visual Basic-Syntax gibt es zwei Möglichkeiten Sie können zum einen eine parallele C#-Syntax verwenden und Handler direkt den Instanzen anfügen. Dazu benötigen Sie das AddHandler -Schlüsselwort und den AddressOf-Operator, der den Handlermethodennamen dereferenziert.

Die zweite Möglichkeit für die Visual Basic-Syntax besteht darin, das Handles-Schlüsselwort für Ereignishandler zu verwenden. Das ist in Fällen angebracht, in denen Handler für Objekte voraussichtlich beim Laden vorhanden sind und für die Objektlebensdauer bestehen bleiben. Wenn Sie Handles für ein in XAML definiertes Objekt verwenden, müssen Sie einen Name/x:Name bereitstellen. Dieser Name wird zum Instanzenqualifizierer, der für den Instance.Event-Teil der Handles-Syntax benötigt wird. In diesem Fall benötigen Sie keinen Ereignishandler, der auf der Objektlebensdauer basiert, um das Anfügen der anderen Ereignishandler einzuleiten. Die Handles-Verbindungen werden beim Kompilieren der XAML-Seite erstellt.


Private Sub textBlock1_PointerEntered(ByVal sender As Object, ByVal e As PointerRoutedEventArgs) Handles textBlock1.PointerEntered
'...
End Sub

Hinweis  Visual Studio und die zugehörige XAML-Entwurfsoberfläche eignen sich im Allgemeinen besser für die Instanzbehandlung als für das Handles-Schlüsselwort. Denn das Erstellen der Ereignishandlerverknüpfung in XAML gehört zu einem typischen Designer-Entwickler-Workflow, und die Handles-Schlüsselworttechnik ist mit dem Verknüpfen der Ereignishandler in XAML nicht kompatibel.

Auch in C++ verwenden Sie die +=-Syntax. Es gibt jedoch Unterschiede zum allgemeinen C#-Format:

  • Es gibt keinen Rückschluss auf Delegaten. Sie müssen deshalb ref new für die Delegatinstanz verwenden.
  • Der Delegatenkonstruktor besitzt zwei Parameter und benötigt das Zielobjekt als ersten Parameter. Normalerweise geben Sie this an.
  • Der Delegatenkonstruktor benötigt die Methodenadresse als zweiten Parameter, sodass die &-Dereferenzierungsoperator vor dem Methodennamen steht.

textBlock1->PointerEntered += 
ref new PointerEventHandler(this,&BlankPage::textBlock1_PointerExited);

Entfernen von Ereignishandlern im Code

Das Entfernen von Ereignishandlern im Code ist in der Regel nicht erforderlich, auch wenn sie von Ihnen im Code hinzugefügt wurden. Das Verhalten der Objektlebensdauer für die meisten Windows-Runtime-Objekte, z. B. Seiten und Steuerelemente, zerstört die Objekte, wenn die Verbindung mit dem Haupt-Window und der dazugehörigen visuellen Struktur getrennt wird. Vorhandene Delegatverweise werden ebenfalls zerstört. In .NET erfolgt dies durch eine Garbage Collection, und in Windows-Runtime mit C++/CX werden standardmäßig schwache Verweise verwendet.

In einigen seltenen Fällen sollten Ereignishandler explizit entfernt werden. Dazu zählen:

  • Für statische Ereignisse hinzugefügte Handler, für die keine konventionelle Garbage Collection durchgeführt werden kann. Die Ereignisse der Klassen CompositionTarget und Clipboard sind Beispiele für statische Ereignisse in der Windows-Runtime-API.
  • Testcode, in dem das Entfernen von Handlern sofort erfolgen soll, oder Code, in dem alte und neue Ereignishandler für ein Ereignis zur Laufzeit ausgetauscht werden sollen.
  • Die Implementierung eines benutzerdefinierten remove-Accessors.
  • Benutzerdefinierte statische Ereignisse.
  • Handler für Seitennavigationen

Bei FrameworkElement.Unloaded oder Page.NavigatedFrom handelt es sich um mögliche Ereignisauslöser mit entsprechenden Positionen in der Zustandsverwaltung und der Objektlebensdauer, sodass sie zum Entfernen von Handlern für andere Ereignisse verwendet werden können.

Beispielsweise können Sie mit diesem Code einen Ereignishandler mit dem Namen textBlock1_PointerEntered aus dem Zielobjekt textBlock1 entfernen.


textBlock1.PointerEntered -= textBlock1_PointerEntered;

Sie können Handler auch in solchen Fällen entfernen, in denen das Ereignis über ein XAML-Attribut hinzugefügt wurde, was bedeutet, dass der Handler in generiertem Code hinzugefügt wurde. Dies ist einfacher, wenn Sie einen Name-Wert für das Element bereitstellen, dem der Handler angehängt wurde, weil dadurch später ein Objektverweis für den Code bereitgestellt wird. Sie können jedoch auch in der Objektstruktur nach dem erforderlichen Objekt suchen, wenn kein Name für das Objekt vorhanden ist.

Wenn Sie einen Ereignishandler in C++/CX entfernen müssen, benötigen Sie ein Registrierungstoken, das Sie im Rückgabewert der +=-Ereignishandlerregistrierung erhalten haben sollten. Der Grund ist, dass es sich bei dem Wert, den Sie für die rechte Seite der Aufhebung der -=-Registrierung in C++/CX-Syntax verwenden, um das Token handelt, nicht beim Methodennamen. Für C++/CX können Sie als XAML-Attribut hinzugefügte Handler nicht entfernen, da der generierte C++/CX-Code kein Token speichert.

Routingereignisse

Die Windows-Runtime mit C#, Microsoft Visual Basic oder C++/CX unterstützt das Konzept von Routingereignissen für eine Gruppe von Ereignissen, die bei den meisten UI-Elementen verwendet werden. Diese Ereignisse werden für Eingabe- und Benutzerinteraktionsszenarien verwendet und in der UIElement-Basisklasse implementiert. Die folgenden Eingabeereignisse sind Routingereignisse:

Ein Routingereignis ist ein Ereignis, das möglicherweise von einem untergeordneten Objekt an jedes seiner übergeordneten Objekte in der Objektstruktur weitergeleitet wird. Die XAML-Struktur Ihrer UI kommt dieser Struktur nahe, wobei der Stamm der Struktur dem Stammelement im XAML entspricht. Die tatsächliche Objektstruktur kann sich von der XAML-Elementschachtelung unterscheiden, da die Objektstruktur keine XAML-Sprachfeatures wie Eigenschaftenelementtags enthält. Routingereignisse durchlaufen die Struktur nach dem Bubblingkonzept von untergeordneten XAML-Objektelementen, die das Ereignis auslösen, zu den übergeordneten Objekten, in denen sie enthalten sind. Das Ereignis und seine Ereignisdaten können für mehrere Objekte entlang der Ereignisroute behandelt werden. Wenn kein Element über Handler verfügt, wird die Route u. U. bis zum Stammelement fortgesetzt.

Wenn Sie Webtechnologien wie Dynamic HTML (DHTML) oder HTML5 kennen, sind Sie möglicherweise bereits mit dem Bubbling-Ereigniskonzept vertraut.

Wenn für ein Routingereignis ein Bubbling durch die zugehörige Ereignisroute erfolgt, greifen alle angefügten Ereignishandler auf eine freigegebene Instanz von Ereignisdaten zu. Deshalb werden Änderungen an Ereignisdaten an den nächsten Handler weitergegeben, wenn einer der Handler Schreibzugriff auf Ereignisdaten besitzt. Die Daten entsprechen dann möglicherweise nicht mehr den ursprünglichen Ereignisdaten. Wenn ein Ereignis ein Routingereignisverhalten besitzt, wird in der Referenzdokumentation entsprechend darauf hingewiesen.

Die OriginalSource-Eigenschaft von RoutedEventArgs

Wenn ein Ereignis entlang einer Route ein Bubbling durchläuft, ist sender nicht mehr das Objekt, das das Ereignis ausgelöst hat. Stattdessen ist sender das Objekt, an das der aufgerufene Handler angefügt ist.

In einigen Fällen interessieren Sie sich nicht für das sender-Objekt, sondern eher dafür, auf welchem der möglichen untergeordneten Objekte sich der Mauszeiger beim Auslösen eines Zeigerereignisses befindet oder welches Objekt in einer größeren UI beim Drücken einer Taste den Fokus hatte. Für diese Fälle können Sie den Wert der OriginalSource-Eigenschaft verwenden. An allen Punkten in der Route meldet OriginalSource das ursprüngliche Objekt, von dem das Ereignis ausgelöst wurde, und nicht das Objekt, dem der Handler angefügt ist. Bei UIElement-Eingabeereignissen ist das ursprüngliche Objekt jedoch häufig ein Objekt, das nicht direkt im XAML für die UI-Definition auf Seitenebene sichtbar ist. Stattdessen kann das ursprüngliche Quellobjekt ein Vorlagenteil eines Steuerelements sein. Wenn der Benutzer z. B. mit dem Mauszeiger auf die äußere Kante eines Button-Objekts zeigt, ist OriginalSource bei den meisten Zeigerereignissen ein Border-Vorlagenteil in der Template und nicht das Button-Objekt selbst.

Tipp  Das Eingabe-Eventbubbling ist besonders dann hilfreich, wenn Sie ein Steuerelement mit Vorlagen erstellen. Auf jedes Steuerelement, das eine Vorlage besitzt, kann durch seinen Consumer eine neue Vorlage angewendet werden. Der Consumer, der eine Arbeitsvorlage erneut zu erstellen versucht, kann versehentlich in der Standardvorlage deklarierten Ereignisbehandlungscode entfernen. Sie können trotzdem eine Ereignisbehandlung auf Steuerelementebene bereitstellen, indem Sie Handler als Teil der OnApplyTemplate-Überschreibung in der Klassendefinition anfügen. Anschließend können Sie die Eingabeereignisse abfangen, die bei der Instanziierung per Bubbling zum Stamm des Steuerelements weitergeleitet werden.

Die Eigenschaft Handled

Einige Ereignisdatenklassen für bestimmte Routingereignisse enthalten eine Eigenschaft mit dem Namen Handled. Beispiele finden Sie unter PointerRoutedEventArgs.Handled, KeyRoutedEventArgs.Handled und DragEventArgs.Handled. Handled ist in allen Fällen eine festlegbare boolesche Eigenschaft.

Wenn die Handled-Eigenschaft auf true festgelegt wird, wirkt sich das auf das Ereignissystemverhalten aus. Ist Handled auf true festgelegt, wird das Routing für die meisten Ereignishandler beendet. Das Ereignis wird nicht über die Route weitergeleitet, um andere angefügte Handler über dieses spezielle Ereignis zu informieren. Was "behandelt" im Kontext des Ereignisses bedeutet und wie Ihre App auf ein behandeltes Ereignis reagiert, liegt in Ihrem Ermessen. Im Grunde ist Handled ein einfaches Protokoll, mit dem im App-Code angegeben werden kann, dass das Auftreten eines Ereignisses nicht per Bubbling an Container weitergeleitet werden muss, da Ihre App-Logik sich um die notwendigen Schritte gekümmert hat. Umgekehrt müssen Sie jedoch darauf achten, dass Sie keine Ereignisse behandeln, die per Bubbling weitergeleitet werden müssen, damit integrierte System- oder Steuerelementverhalten angewendet werden können. Das Behandeln von Ereignissen auf niedriger Ebene innerhalb der Teile oder Elemente eines Auswahlsteuerelements kann sich z. B. nachteilig auswirken. Das Auswahlsteuerelement sucht möglicherweise nach Eingabeereignissen, um festzustellen, ob die Auswahl geändert werden muss.

Nicht alle Routingereignisse können eine Route auf diese Weise abbrechen, und zwar, weil sie keine Handled-Eigenschaft haben. GotFocus und LostFocus werden z. B. immer die gesamte Route bis zum Stamm per Bubbling weitergeleitet, und ihre Ereignisdatenklassen haben keine Handled-Eigenschaft, die dieses Verhalten beeinflussen kann.

Eingabeereignishandler in Steuerelementen

Bei bestimmten Windows Runtime-Steuerelementen wird das Handled-Konzept manchmal intern für Eingabeereignisse verwendet. Dadurch kann der Anschein erweckt werden, dass niemals ein Eingabeereignis eintritt, weil es von Ihrem Benutzercode nicht verarbeitet werden kann Die Button-Klasse enthält z. B. Logik, mit der gezielt das allgemeine Eingabeereignis PointerPressed behandelt wird. Grund hierfür ist, dass Schaltflächen ein Click-Ereignis auslösen, das durch Eingaben mit gedrücktem Zeiger sowie durch andere Eingabemodi initiiert wird (z. B. durch Tasten wie die EINGABETASTE, die die Schaltfläche aufrufen können, wenn sie den Fokus hat). Im Rahmen des Klassendesigns von Button wird das Rohdateneingabe-Ereignis konzeptionell behandelt. Klassenconsumer wie Ihr Benutzercode können stattdessen mit dem steuerungsrelevanten Click-Ereignis interagieren. In den entsprechenden Themen zu den speziellen Steuerelementklassen in der API-Referenz für die Windows-Runtime wird häufig das von der Klasse implementierte Ereignisbehandlungsverhalten erwähnt. In einigen Fällen können Sie das Verhalten ändern, indem Sie OnEvent-Methoden überschreiben. Sie können z. B. ändern, wie Ihre von TextBox abgeleitete Klasse auf Tasteneingaben reagiert, indem Sie Control.OnKeyDown überschreiben.

Registrieren von Handlern für bereits behandelte Routingereignisse

Weiter oben wurde erwähnt, dass die meisten Handler nicht aufgerufen werden, wenn Handled auf true festgelegt ist. Die AddHandler-Methode bietet jedoch eine Technik, um einen Handler anzufügen, der für die Route immer aufgerufen wird. Das geschieht selbst dann, wenn für andere Handler an früherer Stelle in der Route Handled in den geteilten Ereignisdaten auf true festgelegt wurde. Diese Technik ist nützlich, wenn ein von Ihnen verwendetes Steuerelement das Ereignis in seiner inneren Zusammensetzung behandelt hat. Sie eignet sich auch für spezielle Steuerelementlogik, bei der Sie weiterhin mit einer Steuerelementinstanz oder Ihrer App-UI auf das Ereignis reagieren möchten. Diese Technik sollte jedoch mit Bedacht eingesetzt werden, da sie dem Zweck von Handled widersprechen und die beabsichtigten Interaktionen des Steuerelements verhindern kann.

Nur Routingereignisse mit entsprechenden Routingereignisbezeichnern können die Technik zur AddHandler-Ereignisbehandlung nutzen, da der Bezeichner als Eingabe für die AddHandler-Methode erforderlich ist. In der Referenzdokumentation zu AddHandler finden Sie eine Liste der Ereignisse, für die Routingereignisbezeichner verfügbar sind. Diese Liste stimmt größtenteils mit der bereits gezeigten Liste mit Routingereignissen überein. Die letzten beiden Ereignisse in der Liste, GotFocus und LostFocus, stellen eine Ausnahme dar, da sie keinen Routingereignisbezeichner besitzen. Daher können Sie AddHandler nicht für diese Ereignisse verwenden.

Routingereignisse außerhalb der visuellen Struktur

Bestimmte Objekte sind Bestandteil einer Beziehung mit der primären visuellen Struktur. Diese ist konzeptionell wie z. B. eine Überlagerung über die visuellen Hauptobjekte. Diese bestimmten Objekte gehören nicht zu den üblichen Beziehungen zwischen übergeordneten und untergeordneten Elementen, mit denen alle Strukturelemente mit dem visuellen Stamm verbunden sind. Das betrifft jedes angezeigte Popup- oder ToolTip-Element. Wenn Sie Routingereignisse eines Popup- oder ToolTip-Elements behandeln möchten, platzieren Sie die Handler für bestimmte UI-Elemente innerhalb des Popup- oder ToolTip-Elements und nicht direkt für das Popup- oder ToolTip-Element. Verlassen Sie sich nicht auf das Routing innerhalb einer Zusammensetzung, die für Popup- oder ToolTip-Inhalt ausgeführt wird. Denn das Ereignisrouting funktioniert nur entlang der visuellen Hauptstruktur. Ein Popup- oder ToolTip-Element wird nicht als übergeordnetes Element von untergeordneten UI-Elementen angesehen und empfängt das Routingereignis in keinem Fall, selbst wenn es versucht, Elemente wie den Popup-Standardhintergrund als Erfassungsbereich für Eingabeereignisse zu verwenden.

Treffertests und Eingabeereignissse

Das Bestimmen, ob und wo auf der UI ein Element für die Maus-, Touch und Stifteingabe sichtbar ist, wird als Treffertests bezeichnet. Bei Toucheingabeaktionen und interaktionsspezifischen Ereignissen oder Manipulationsereignissen, die aus einer Toucheingabeaktion resultieren, muss ein Element bei Treffertests sichtbar sein, damit es der Ereignisquelle entsprechen und das der Aktion zugeordnete Ereignis auslösen kann. Andernfalls durchläuft die Aktion das Element bis zu zugrunde liegenden oder übergeordneten Elementen in der visuellen Struktur, die mit dieser Eingabe interagieren könnte. Treffertests werden von mehreren Faktoren beeinflusst. Sie können jedoch feststellen, ob ein bestimmtes Element Eingabeereignisse auslösen kann, indem Sie die zugehörige IsHitTestVisible-Eigenschaft überprüfen. Diese Eigenschaft gibt true nur dann zurück, wenn das Element die folgenden Kriterien erfüllt:

  • Der Visibility-Eigenschaftenwert des Elements ist Visible.
  • Der Background- oder Fill-Eigenschaftswert des Elements ist nicht null. Ein null-Wert für Brush führt zur Transparenz und Unsichtbarkeit von Treffertests. (Wenn Sie ein Element transparent machen und zugleich Treffertests für das Element ermöglichen möchten, verwenden Sie einen Transparent-Pinsel anstelle von null.)

    Hinweis  Background und Fill werden nicht durch UIElement, sondern durch unterschiedliche abgeleitete Klassen wie Control und Shape definiert. Die von Ihnen für Vorder- und Hintergrundeigenschaften verwendeten Implikationen von Pinseln sind jedoch für Treffertests und Eingabeereignisse identisch. Dabei ist es unerheblich, welche Unterklasse die Eigenschaften implementiert.

  • Wenn das Element ein Steuerelement ist, muss der zugehörige IsEnabled-Eigenschaftenwert auf true festgelegt sein.
  • Das Element muss im Layout über reale Dimensionen verfügen. Ein Element, bei dem ActualHeight und ActualWidth 0 sind, kann keine Eingabeereignisse auslösen.

Bei einigen Steuerelementen sind besondere Regeln bezüglich Treffertests zu beachten. TextBlock hat beispielsweise keine Background-Eigenschaft. Dennoch können innerhalb des gesamten Bereichs der zugehörigen Dimensionen Treffertests ausgeführt werden. Für Image- und MediaElement-Steuerelemente können in den zugehörigen definierten Rechtecksdimensionen Treffertests ausgeführt werden. Dabei ist es unerheblich, ob in der Medienquelldatei transparente Inhalte wie Alphakanäle angezeigt werden. WebView-Steuerelemente weisen ein spezielles Treffertestverhalten auf, weil die Eingabe durch gehostete HTML behandelt werden und Skriptereignisse auslösen kann.

Für die meisten Panel-Klassen und Border-Elemente können im eigenen Hintergrund zwar keine Treffertests ausgeführt werden, sie können aber trotzdem Benutzereingabeereignisse verarbeiten, die von den in ihnen integrierten Elementen weitergeleitet werden.

Elemente, die sich an der gleichen Position wie ein Benutzereingabeereignis befinden, können unabhängig davon ermittelt werden, ob sie für Treffertests infrage kommen. Rufen Sie dazu die FindElementsInHostCoordinates-Methode auf. Diese Methode findet die Elemente, wie der Name nahe legt, an einer Position relativ zu einem angegebenen Hostelement. Transformationen und Layoutänderungen können sich jedoch auf das Koordinatensystem eines Elements auswirken und somit die an einer bestimmten Position gefundenen Elemente beeinflussen.

Steuerung

Eine geringe Anzahl von UI-Elementen unterstützt die Steuerung. Die Steuerung verwendet eingabebezogene Routingereignisse in der zugrunde liegenden Implementierung und ermöglicht die Verarbeitung verwandter UI-Eingaben (eine bestimmte Zeigeraktion oder Zugriffstaste) durch das Aufrufen eines einzelnen Befehlshandlers. Wenn die Steuerung für ein UI-Element verfügbar ist, sollten Sie dessen Steuerungs-APIs verwenden anstelle einzelner Eingabeereignisse. Normalerweise verwenden Sie einen Binding-Verweis auf Eigenschaften einer Klasse, die das Ansichtsmodell für Daten definiert. Die Eigenschaften enthalten benannte Befehle, die sprachspezifische ICommand-Steuerungsmuster implementieren. Weitere Informationen finden Sie unter ButtonBase.Command.

Benutzerdefinierte Ereignisse in der Windows-Runtime

Beim Definieren von benutzerdefinierten Ereignissen hängt die Vorgehensweise beim Hinzufügen des Ereignisses und die Bedeutung für Ihren Klassenentwurf erheblich von der verwendeten Programmiersprache ab.

  • Für C# und Visual Basic definieren Sie ein CLR-Ereignis. Sie können das .NET-Standardereignismuster verwenden, es sei denn, Sie verwenden benutzerdefinierte Accessoren (add/remove). Zusätzliche Tipps:
  • Für C++/CX lesen Sie Ereignisse (C++/CX).
    • Verwenden Sie auch für Ihre eigenen Verwendungen von benutzerdefinierten Ereignissen benannte Verweise. Verwenden Sie nicht Lambda für benutzerdefinierte Ereignisse, da dadurch u. U. ein Zirkelverweis erstellt wird.

Sie können ein benutzerdefiniertes Routingereignis nicht für die Windows-Runtime deklarieren; Routingereignisse sind auf den Satz aus der Windows-Runtime beschränkt.

Das Definieren eines benutzerdefinierten Ereignisses erfolgt in der Regel im Rahmen der Definition eines benutzerdefinierten Steuerelements. Eine Abhängigkeitseigenschaft mit einem Rückruf für Eigenschaftsänderungen ist ein gängiges Muster, genau wie das Definieren eines benutzerdefinierten Ereignisses, das in manchen oder in allen Fällen durch den Abhängigkeitseigenschaftsrückruf ausgelöst wird. Benutzer Ihres Steuerelements haben keinen Zugriff auf den von Ihnen definierten Rückruf für Eigenschaftsänderungen; die beste Methode ist das Bereitstellen eines Benachrichtigungsereignisses. Weitere Informationen finden Sie unter Benutzerdefinierte Abhängigkeitseigenschaften.

Verwandte Themen

Übersicht über XAML
Schnellstart: Toucheingabe
Reaktion auf Tastatureingaben
.NET-Ereignisse und -Delegate
Erstellen von Windows-Runtime-Komponenten
AddHandler

 

 

Anzeigen:
© 2014 Microsoft