Översikt över bifogade händelser (WPF .NET)
XAML (Extensible Application Markup Language) definierar en språkkomponent och händelsetyp som kallas en bifogad händelse. Anslutna händelser kan användas för att definiera en ny dirigerad händelse i en icke-elementklass och utlösa händelsen på vilket element som helst i ditt träd. För att göra det måste du registrera den bifogade händelsen som en dirigerad händelse och ange specifik stödjande kod som stöder funktionalitet för bifogade händelser. Eftersom anslutna händelser registreras som routade händelser sprids de genom elementträdet när de genereras på ett element.
Förutsättningar
Artikeln förutsätter grundläggande kunskaper om routade händelser i Windows Presentation Foundation (WPF) och att du har läst Översikt över routade händelser och XAML i WPF. Om du vill följa exemplen i den här artikeln hjälper det om du är bekant med XAML och vet hur du skriver WPF-program.
Bifogad händelsesyntax
I XAML-syntax anges en bifogad händelse med dess händelsenamn och dess ägartyp, i form av <owner type>.<event name>
. Eftersom händelsenamnet är kvalificerat med namnet på dess ägartyp tillåter syntaxen att händelsen kopplas till alla element som kan instansieras. Den här syntaxen gäller även för hanterare för vanliga routade händelser som kopplas till ett godtyckligt element längs händelsevägen.
Följande XAML-attributsyntax kopplar AquariumFilter_Clean
-hanteraren för den AquariumFilter.Clean
kopplade händelsen till aquarium1
-elementet:
<aqua:Aquarium x:Name="aquarium1" Height="300" Width="400" aqua:AquariumFilter.Clean="AquariumFilter_Clean"/>
I det här exemplet är aqua:
-prefixet nödvändigt eftersom AquariumFilter
- och Aquarium
-klasserna finns i ett annat CLR-namnområde (Common Language Runtime) och sammansättning.
Du kan också koppla hanterare för anslutna händelser i bakomliggande kod. Det gör du genom att anropa metoden AddHandler på objektet som hanteraren ska koppla till och skicka händelseidentifieraren och hanteraren som parametrar till metoden.
Så implementerar WPF anslutna händelser
WPF-kopplade händelser implementeras som routade händelser som backas upp av ett RoutedEvent fält. Därför sprids bifogade händelser genom elementträdet när de har genererats. I allmänhet är det objekt som genererar den anslutna händelsen, som kallas händelsekällan, en system- eller tjänstkälla. System- eller tjänstkällor är inte en direkt del av elementträdet. För andra anslutna händelser kan händelsekällan vara ett element i trädet, till exempel en komponent i en sammansatt kontroll.
Kopplade händelsescenarier
I WPF används anslutna händelser i vissa funktionsområden där det finns en abstraktion på tjänstnivå. WPF använder till exempel anslutna händelser som aktiveras av statiska Mouse eller Validation klasser. Klasser som interagerar med eller använder en tjänst kan antingen interagera med en händelse med hjälp av kopplad händelsesyntax eller visa den anslutna händelsen som en dirigerad händelse. Det senare alternativet är en del av hur en klass kan integrera funktionerna i tjänsten.
WPF-indatasystemet använder anslutna händelser i stor utsträckning. Nästan alla dessa kopplade händelser visas dock som motsvarande okopplade dirigerade händelser via baselement. Varje dirigerad indatahändelse är medlem i baselementklassen och backas upp med en CLR-händelse "wrapper". Du använder eller hanterar sällan anslutna händelser direkt. Det är till exempel enklare att hantera den underliggande kopplade händelsen Mouse.MouseDown på en UIElement via den motsvarande dirigerade händelsen UIElement.MouseDown än med hjälp av kopplad händelsesyntax i XAML eller kod bakom.
Anslutna händelser har ett arkitektursyfte genom att möjliggöra framtida expansion av indataenheter. Till exempel skulle en ny indataenhet bara behöva höja Mouse.MouseDown
för att simulera musindata, och den skulle inte behöva härledas från Mouse
för att göra det. Det scenariot omfattar kodhantering av händelsen, eftersom XAML-hanteringen av den bifogade händelsen inte skulle vara relevant.
Hantera en bifogad händelse
Processen för att koda och hantera en bifogad händelse är i princip densamma som för en icke-ansluten dirigerad händelse.
Som tidigarenämnts är befintliga WPF-kopplade händelser vanligtvis inte avsedda att hanteras direkt i WPF. Oftast är syftet med en bifogad händelse att aktivera ett element i en sammansatt kontroll för att rapportera dess tillstånd till ett överordnat element i kontrollen. I det scenariot genereras händelsen i kod och förlitar sig på klasshantering i relevant överordnad klass. Objekt i en Selector förväntas till exempel utlösa den kopplade händelsen Selected, som sedan hanteras av klassen Selector
. Klassen Selector
konverterar potentiellt händelsen Selected
till ett dirigerat event av typ SelectionChanged. Mer information om routade händelser och klasshantering finns i Märkning av dirigerade händelser som hanterade och klasshantering.
Definiera en anpassad bifogad händelse
Om du härleder från vanliga WPF-basklasser kan du implementera din anpassade kopplade händelse genom att inkludera två åtkomstmetoder i klassen. Dessa metoder är:
En Lägg till<händelsenamn>Handler-metoden, med en första parameter som är det element som händelsehanteraren är kopplad till och en andra parameter som är den händelsehanterare som ska läggas till. Metoden måste vara
public
ochstatic
, utan returvärde. Metoden anropar basklassmetoden AddHandler, genom att skicka med den dirigerade händelsen och hanteraren som argument. Den här metoden stöder XAML-attributsyntaxen för att koppla en händelsehanterare till ett element. Den här metoden ger också kodåtkomst till händelsehanterararkivet för den anslutna händelsen.Ett Ta bort<-händelsenamn>-hanterare-metoden, med en första parameter som är elementet som händelsehanteraren är kopplad till, och en andra parameter som är den händelsehanterare som ska tas bort. Metoden måste vara
public
ochstatic
, utan returvärde. Metoden anropar basklassmetoden RemoveHandler och skickar in den dirigerade händelsen och hanteraren som argument. Den här metoden ger kodåtkomst till händelsehanterararkivet för den anslutna händelsen.
WPF implementerar anslutna händelser som routade händelser eftersom identifieraren för en RoutedEvent definieras av WPF-händelsesystemet. Routning av en händelse är också en naturlig förlängning av konceptet med en bifogad händelse på XAML-språknivå. Den här implementeringsstrategin begränsar hanteringen av kopplade händelser till antingen UIElement härledda klasser eller ContentElement härledda klasser, eftersom endast dessa klasser har AddHandler implementeringar.
Till exempel definierar följande kod Clean
den kopplade händelsen på ägarklassen AquariumFilter
, vilket inte är en elementklass. Koden definierar den anslutna händelsen som en dirigerad händelse och implementerar de nödvändiga accessor-metoderna.
public class AquariumFilter
{
// Register a custom routed event using the bubble routing strategy.
public static readonly RoutedEvent CleanEvent = EventManager.RegisterRoutedEvent(
"Clean", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
// Provide an add handler accessor method for the Clean event.
public static void AddCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is not UIElement uiElement)
return;
uiElement.AddHandler(CleanEvent, handler);
}
// Provide a remove handler accessor method for the Clean event.
public static void RemoveCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is not UIElement uiElement)
return;
uiElement.RemoveHandler(CleanEvent, handler);
}
}
Public Class AquariumFilter
' Register a custom routed event using the bubble routing strategy.
Public Shared ReadOnly CleanEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
"Clean", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
' Provide an add handler accessor method for the Clean event.
Public Shared Sub AddCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)
If uiElement IsNot Nothing Then
uiElement.[AddHandler](CleanEvent, handler)
End If
End Sub
' Provide a remove handler accessor method for the Clean event.
Public Shared Sub RemoveCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)
If uiElement IsNot Nothing Then
uiElement.[RemoveHandler](CleanEvent, handler)
End If
End Sub
End Class
Den RegisterRoutedEvent metod som returnerar den anslutna händelseidentifieraren är samma metod som används för att registrera icke-anslutna routade händelser. Både anslutna och icke-anslutna dirigerade händelser registreras i ett centraliserat internt arkiv. Den här implementeringen av händelsearkivet möjliggör begreppet "händelser som ett gränssnitt" som beskrivs i Översikt över routade händelser.
Till skillnad från 'wrapper'-händelsen i CLR som används för att stötta icke-anslutna routade händelser, kan metoderna för tillgång till anslutna händelser implementeras i klasser som inte är härledda från UIElement eller ContentElement. Detta är möjligt eftersom den anslutna koden för händelsestöd anropar metoderna UIElement.AddHandler och UIElement.RemoveHandler på en skickad UIElement
instans. Däremot anropar CLR-omslutningen för icke-anslutna routade händelser dessa metoder direkt i ägande klassen, så att klassen måste härledas från UIElement
.
Utlysa en WPF-bifogad händelse
Processen för att skapa en bifogad händelse är i stort sett densamma som för en icke-ansluten dirigerad händelse.
Vanligtvis behöver koden inte generera några befintliga WPF-definierade kopplade händelser eftersom dessa händelser följer den allmänna konceptmodellen "tjänst". I den modellen ansvarar tjänstklasser, till exempel InputManager, för att utlösa WPF-definierade kopplade händelser.
När du definierar en anpassad bifogad händelse med WPF-modellen för att basera bifogade händelser på dirigerade händelser, använder du metoden UIElement.RaiseEvent för att utlösa en bifogad händelse på alla UIElement eller ContentElement. När du skapar en dirigerad händelse, oavsett om den är kopplad eller inte, måste du ange ett element i elementträdet som händelsekälla. Källan rapporteras sedan som anroparen RaiseEvent
. Om du till exempel vill utlösa den AquariumFilter.Clean
kopplade dirigerade händelsen på aquarium1
:
aquarium1.RaiseEvent(new RoutedEventArgs(AquariumFilter.CleanEvent));
aquarium1.[RaiseEvent](New RoutedEventArgs(AquariumFilter.CleanEvent))
I föregående exempel är aquarium1
händelsekällan.
Se även
.NET Desktop feedback