Přehled směrovaných událostí
Toto téma popisuje koncept směrovaných událostí ve Windows Presentation Foundation (WPF). Téma definuje terminologii směrovaných událostí, popisuje způsob směrování směrovaných událostí přes strom prvků, shrnuje způsob zpracování směrovaných událostí a představuje způsob vytvoření vlastních směrovaných událostí.
Požadavky
V tomto tématu se předpokládá, že máte základní znalosti modulu CLR (Common Language Runtime) a objektově orientovaného programování a také koncept, jak lze vztahy mezi elementy WPF konceptualizovat jako strom. Abyste mohli postupovat podle příkladů v tomto tématu, měli byste také porozumět jazyku XAML (Extensible Application Markup Language) a vědět, jak psát velmi základní aplikace nebo stránky WPF. Další informace naleznete v tématu Návod: Moje první desktopová aplikace WPF a XAML ve WPF.
Co je směrovaná událost?
Směrované události si můžete představit z hlediska funkčnosti nebo implementace. Obě definice jsou zde uvedeny, protože někteří lidé najdou jednu nebo druhou definici užitečnější.
Funkční definice: Směrovaná událost je typ události, která může vyvolat obslužné rutiny na více naslouchacích procesů ve stromu elementů, nikoli jen na objektu, který vyvolal událost.
Definice implementace: Směrovaná událost je událost CLR, která je podporována instancí RoutedEvent třídy a je zpracována systémem událostí Windows Presentation Foundation (WPF).
Typická aplikace WPF obsahuje mnoho prvků. Ať už jsou vytvořené v kódu nebo deklarované v XAML, tyto prvky existují ve vztahu stromu elementů k sobě navzájem. Trasa události může v závislosti na definici události cestovat jedním ze dvou směrů, ale obvykle trasa prochází ze zdrojového prvku a pak "bubliny" prochází stromem elementu, dokud nedosáhne kořene stromu elementu (obvykle stránka nebo okno). Pokud jste dříve pracovali s objektovým modelem DHTML, může vám být tento koncept bublání známý.
Představte si následující jednoduchý strom elementů:
<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
<StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
<Button Name="YesButton" Width="Auto" >Yes</Button>
<Button Name="NoButton" Width="Auto" >No</Button>
<Button Name="CancelButton" Width="Auto" >Cancel</Button>
</StackPanel>
</Border>
Tento strom elementu vytvoří něco jako následující:
V tomto zjednodušeném stromu elementů Click je zdrojem události jeden z Button prvků a podle toho Button , na co jste klikli, je první prvek, který má možnost zpracovat událost. Pokud ale žádná obslužná rutina připojená k Button akcím na události, událost se v Button nadřazeném stromu elementu StackPanel, což je . Event bubbles to Bordera then beyond to the page root of the element tree (not shown).
Jinými slovy, trasa události pro tuto Click událost je:
Button--StackPanel>--Border>--...>
Scénáře nejvyšší úrovně pro směrované události
Následuje stručný přehled scénářů, které motivovaly koncept směrované události a proč typická událost CLR nebyla pro tyto scénáře vhodná:
Složení a zapouzdření ovládacích prvků: Různé ovládací prvky v WPF mají bohatou kon režim stanu l. Můžete například umístit obrázek uvnitř objektu Button, který efektivně rozšiřuje vizuální strom tlačítka. Přidaný obrázek však nesmí přerušit chování při testování, které způsobí, že tlačítko odpoví na Click jeho obsah, i když uživatel klikne na pixely, které jsou technicky součástí obrázku.
Body přílohy jedné obslužné rutiny: V model Windows Forms byste museli ke zpracování událostí, které by mohly být vyvolány z více prvků, připojit stejnou obslužnou rutinu vícekrát. Směrované události umožňují připojit tuto obslužnou rutinu pouze jednou, jak je znázorněno v předchozím příkladu, a pomocí logiky obslužné rutiny určit, odkud událost pochází v případě potřeby. Může to být například obslužná rutina pro dříve zobrazený KÓD XAML:
private void CommonClickHandler(object sender, RoutedEventArgs e)
{
FrameworkElement feSource = e.Source as FrameworkElement;
switch (feSource.Name)
{
case "YesButton":
// do something here ...
break;
case "NoButton":
// do something ...
break;
case "CancelButton":
// do something ...
break;
}
e.Handled=true;
}
Private Sub CommonClickHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim feSource As FrameworkElement = TryCast(e.Source, FrameworkElement)
Select Case feSource.Name
Case "YesButton"
' do something here ...
Case "NoButton"
' do something ...
Case "CancelButton"
' do something ...
End Select
e.Handled=True
End Sub
Zpracování tříd: Směrované události umožňují statickou obslužnou rutinu definovanou třídou. Tato obslužná rutina třídy má možnost zpracovat událost dříve, než mohou všechny připojené obslužné rutiny instance.
Odkazování na událost bez reflexe: Určité techniky kódu a značek vyžadují způsob, jak identifikovat konkrétní událost. Směrovaná událost vytvoří RoutedEvent pole jako identifikátor, který poskytuje robustní techniku identifikace událostí, která nevyžaduje statický nebo běhový odraz.
Způsob implementace směrovaných událostí
Směrovaná událost je událost CLR, která je podporována instancí RoutedEvent třídy a zaregistrována v systému událostí WPF. Instance RoutedEvent získaná z registrace se obvykle uchovává jako public
static
readonly
člen pole třídy, která registruje a tedy "vlastní" směrovanou událost. Připojení ke shodné pojmenované události CLR (což se někdy označuje jako událost obálky) se provádí přepsáním add
a remove
implementacemi události CLR. Obvykle platí, že a add
jsou ponechány jako implicitní výchozí, remove
která používá odpovídající syntaxi událostí specifickou pro jazyk pro přidání a odebrání obslužných rutin této události. Směrované zálohování událostí a mechanismus připojení je koncepčně podobný tomu, jak je vlastnost závislosti CLR, která je podporována DependencyProperty třídou a registrována v systému vlastností WPF.
Následující příklad ukazuje deklaraci vlastní Tap
směrované události, včetně registrace a vystavení RoutedEvent pole identifikátoru a add
remove
implementací události Tap
CLR.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
"Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));
// Provide CLR accessors for the event
public event RoutedEventHandler Tap
{
add { AddHandler(TapEvent, value); }
remove { RemoveHandler(TapEvent, value); }
}
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent("Tap", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(MyButtonSimple))
' Provide CLR accessors for the event
Public Custom Event Tap As RoutedEventHandler
AddHandler(ByVal value As RoutedEventHandler)
Me.AddHandler(TapEvent, value)
End AddHandler
RemoveHandler(ByVal value As RoutedEventHandler)
Me.RemoveHandler(TapEvent, value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.RaiseEvent(e)
End RaiseEvent
End Event
Směrované obslužné rutiny událostí a XAML
Chcete-li přidat obslužnou rutinu události pomocí XAML, deklarujete název události jako atribut elementu, který je naslouchací proces událostí. Hodnota atributu je název implementované metody obslužné rutiny, která musí existovat v částečné třídě souboru kódu za kódem.
<Button Click="b1SetColor">button</Button>
Syntaxe XAML pro přidání standardních obslužných rutin událostí CLR je stejná pro přidání směrovaných obslužných rutin událostí, protože skutečně přidáváte obslužné rutiny do obálky událostí CLR, která má pod ní směrovanou implementaci události. Další informace o přidávání obslužných rutin událostí v XAML naleznete v jazyce XAML ve WPF.
Strategie směrování
Směrované události používají jednu ze tří strategií směrování:
Bublování: Vyvolá se obslužné rutiny událostí ve zdroji události. Směrovaná událost pak směruje do po sobě jdoucích nadřazených prvků, dokud se nedosáhne kořene stromu elementu. Většina směrovaných událostí používá strategii směrování bublání. Směrované události bublání se obvykle používají k hlášení změn vstupu nebo stavu z odlišných ovládacích prvků nebo jiných prvků uživatelského rozhraní.
Direct: Pouze samotný zdrojový prvek má možnost vyvolat obslužné rutiny v odpovědi. Je to podobné "směrování", které model Windows Forms používá pro události. Na rozdíl od standardní události CLR však přímé směrované události podporují zpracování tříd (zpracování tříd je vysvětleno v nadcházející části) a lze je používat EventSetter pomocí a EventTrigger.
Tunelování: Zpočátku se vyvolá obslužné rutiny událostí v kořenovém stromu elementu. Směrovaná událost pak prochází trasu po sobě jdoucími podřízenými prvky podél trasy směrem k prvku uzlu, který je směrovaným zdrojem událostí (prvek, který vyvolal směrovanou událost). Směrované události tunelování se často používají nebo zpracovávají jako součást vytváření ovládacího prvku, aby události ze složených částí mohly být záměrně potlačeny nebo nahrazeny událostmi, které jsou specifické pro úplné řízení. Vstupní události poskytované ve WPF se často implementují jako dvojice tunelování nebo bublání. Události tunelování se také někdy označují jako události ve verzi Preview, a to kvůli konvenci pojmenování, která se používá pro páry.
Proč používat směrované události?
Jako vývojář aplikací nemusíte vždy vědět ani se starat o to, že událost, kterou zpracováváte, je implementovaná jako směrovaná událost. Směrované události mají zvláštní chování, ale toto chování je z velké části neviditelné, pokud zpracováváte událost na prvku, ve kterém je vyvolána.
Pokud se směrované události stanou výkonnými, je použití některého z navrhovaných scénářů: definování běžných obslužných rutin ve společném kořenovém adresáři, vytvoření vlastního ovládacího prvku nebo definování vlastní třídy ovládacích prvků.
Směrované naslouchací procesy událostí a směrované zdroje událostí nemusí sdílet společnou událost v jejich hierarchii. Libovolný UIElement nebo ContentElement může být naslouchací proces událostí pro libovolnou směrovanou událost. Proto můžete použít úplnou sadu směrovaných událostí dostupných v celé pracovní sadě rozhraní API jako koncepční "rozhraní", kde různorodé prvky v aplikaci mohou vyměňovat informace o událostech. Tento koncept "rozhraní" pro směrované události platí zejména pro vstupní události.
Směrované události lze také použít ke komunikaci prostřednictvím stromu elementů, protože data událostí události jsou pro každý prvek v trase uložena. Jeden prvek by mohl něco změnit v datech události a tato změna by byla k dispozici pro další prvek v trase.
Kromě aspektu směrování existují dva další důvody, proč by každá daná událost WPF mohla být implementována jako směrovaná událost místo standardní události CLR. Pokud implementujete vlastní události, můžete také zvážit tyto principy:
Některé funkce stylů a šablon WPF, například EventSetter a EventTrigger vyžadují, aby odkazovaná událost byla směrovanou událostí. Toto je scénář identifikátoru události, který jsme zmínili dříve.
Směrované události podporují mechanismus zpracování tříd, kdy třída může určit statické metody, které mají možnost zpracovávat směrované události předtím, než k nim budou mít přístup všechny registrované obslužné rutiny instance. To je velmi užitečné při návrhu řízení, protože vaše třída může vynutit chování třídy řízené událostmi, které nelze omylem potlačit zpracováním události v instanci.
Každý z výše uvedených aspektů je popsán v samostatné části tohoto tématu.
Přidání a implementace obslužné rutiny události pro směrovanou událost
Chcete-li přidat obslužnou rutinu události v XAML, stačí přidat název události do elementu jako atribut a nastavit hodnotu atributu jako název obslužné rutiny události, která implementuje odpovídající delegát, jako v následujícím příkladu.
<Button Click="b1SetColor">button</Button>
b1SetColor
je název implementované obslužné rutiny, která obsahuje kód, který zpracovává Click událost.
b1SetColor
musí mít stejný podpis jako RoutedEventHandler delegát, což je delegát obslužné rutiny události pro Click událost. První parametr všech směrovaných obslužných rutin událostí delegáty určuje prvek, do kterého je přidána obslužná rutina události, a druhý parametr určuje data události.
void b1SetColor(object sender, RoutedEventArgs args)
{
//logic to handle the Click event
}
Private Sub b1SetColor(ByVal sender As Object, ByVal args As RoutedEventArgs)
'logic to handle the Click event
End Sub
RoutedEventHandler je základní delegát směrované obslužné rutiny události. U směrovaných událostí, které jsou specializované pro určité ovládací prvky nebo scénáře, můžou se delegáti používat pro obslužné rutiny směrovaných událostí také specializovaných, aby mohli přenášet specializovaná data událostí. Například v běžném vstupním scénáři můžete zpracovat DragEnter směrovanou událost. Vaše obslužná rutina by měla implementovat delegáta DragEventHandler . Pomocí nejvýraznějšího delegáta můžete zpracovat obslužnou rutinu DragEventArgs a přečíst Data vlastnost, která obsahuje datovou část schránky operace přetažení.
Úplný příklad přidání obslužné rutiny události do elementu pomocí XAML naleznete v tématu Zpracování směrované události.
Přidání obslužné rutiny pro směrovanou událost v aplikaci vytvořené v kódu je jednoduché. Obslužné rutiny směrovaných událostí je možné vždy přidat pomocí pomocné metody AddHandler (což je stejná metoda jako existující backingová volání add
.) Existující směrované události WPF však obecně mají záložní implementace add
a remove
logiku, které umožňují obslužným rutinám směrovaných událostí přidat syntaxi událostí specifickou pro jazyk, což je intuitivnější syntaxe než pomocná metoda. Následuje příklad použití pomocné metody:
void MakeButton()
{
Button b2 = new Button();
b2.AddHandler(Button.ClickEvent, new RoutedEventHandler(Onb2Click));
}
void Onb2Click(object sender, RoutedEventArgs e)
{
//logic to handle the Click event
}
Private Sub MakeButton()
Dim b2 As New Button()
b2.AddHandler(Button.ClickEvent, New RoutedEventHandler(AddressOf Onb2Click))
End Sub
Private Sub Onb2Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
'logic to handle the Click event
End Sub
Následující příklad ukazuje syntaxi operátoru jazyka C# (Visual Basic má mírně odlišnou syntaxi operátoru z důvodu jeho zpracování dereferencingu):
void MakeButton2()
{
Button b2 = new Button();
b2.Click += new RoutedEventHandler(Onb2Click2);
}
void Onb2Click2(object sender, RoutedEventArgs e)
{
//logic to handle the Click event
}
Private Sub MakeButton2()
Dim b2 As New Button()
AddHandler b2.Click, AddressOf Onb2Click2
End Sub
Private Sub Onb2Click2(ByVal sender As Object, ByVal e As RoutedEventArgs)
'logic to handle the Click event
End Sub
Příklad přidání obslužné rutiny události v kódu naleznete v tématu Přidání obslužné rutiny události pomocí kódu.
Pokud používáte Jazyk Visual Basic, můžete také pomocí klíčového Handles
slova přidat obslužné rutiny jako součást deklarací obslužné rutiny. Další informace naleznete v tématu Visual Basic a WPF Event Handling.
Koncept zpracovaných
Všechny směrované události sdílejí společnou třídu datové základny událostí , RoutedEventArgs.
RoutedEventArgs
Handled definuje vlastnost, která přebírá logickou hodnotu. Účelem Handled vlastnosti je povolit jakoukoli obslužnou rutinu události podél trasy označit směrovanou událost jako zpracována, nastavením hodnoty Handled na true
. Po zpracování obslužnou rutinou na jednom prvku podél trasy se sdílená data událostí znovu hlásí každému naslouchacímu procesu podél trasy.
Hodnota Handled má vliv na to, jak se směrovaná událost hlásí nebo zpracuje, když se dále pohybuje podél trasy. Pokud Handled jsou true
v datech událostí pro směrovanou událost, obslužné rutiny, které naslouchají této směrované události u jiných prvků, se pro tuto konkrétní instanci události obecně nevyvolají. To platí jak pro obslužné rutiny připojené v jazyce XAML, tak pro obslužné rutiny přidané syntaxí přílohy obslužné rutiny události specifické pro jazyk, jako +=
je nebo Handles
. U nejběžnějších scénářů obslužné rutiny označte událost, která je zpracována nastavením Handled pro true
zastavení směrování pro trasu tunelování nebo bublinovou trasu, a také pro jakoukoli událost, která je zpracována v bodě trasy obslužnou rutinou třídy.
Existuje však mechanismus "handledEventsToo", kdy naslouchací procesy mohou stále spouštět obslužné rutiny v reakci na směrované události, kde Handled jsou true
v datech události. Jinými slovy, trasa události není skutečně zastavena tím, že označí data události jako zpracovávaná. V kódu můžete použít pouze mechanismus handledEventsToo nebo v EventSetter:
V kódu místo použití syntaxe událostí specifické pro jazyk, která funguje pro obecné události CLR, zavolejte WPF metodu AddHandler(RoutedEvent, Delegate, Boolean) pro přidání obslužné rutiny. Zadejte hodnotu
handledEventsToo
jakotrue
.V objektu EventSetter, nastavte HandledEventsToo atribut na
true
hodnotu .
Kromě chování, které Handled stav vytváří v směrovaných událostech, má koncept dopadu na to Handled , jak navrhnout aplikaci a napsat kód obslužné rutiny události. Můžete konceptualizovat Handled jako jednoduchý protokol, který je vystavený směrovanými událostmi. Přesně to, jak tento protokol používáte, je na vás, ale koncepční návrh, jak se má hodnota Handled použít, je následující:
Pokud je směrovaná událost označena jako zpracována, není nutné ji znovu zpracovat jinými prvky podél této trasy.
Pokud směrovaná událost není označena jako zpracována, ostatní naslouchací procesy, které byly dříve na trase zvoleny, buď neregistrují obslužnou rutinu, nebo obslužné rutiny, které byly zaregistrovány, se rozhodly nepracovat s daty událostí a nastavit Handled na
true
. (Nebo je samozřejmě možné, že aktuální naslouchací proces je prvním bodem trasy.) Obslužné rutiny v aktuálním naslouchacím procesu teď mají tři možné kurzy akce:Nepromýšlejte vůbec žádnou akci; událost zůstane neošetřená a událost se směruje do dalšího naslouchacího procesu.
Spusťte kód v reakci na událost, ale ujistěte se, že provedená akce nebyla dostatečně podstatná, aby bylo možno událost označit jako zpracovanou. Událost směruje na další naslouchací proces.
Spusťte kód v reakci na událost. Označte událost jako zpracovávanou v datech události předávaných obslužné rutině, protože podniknutá akce byla považována za dostatečně podstatnou, aby bylo zaručeno označení jako zpracovávané. Událost stále směruje na další naslouchací proces, ale s Handled=
true
daty událostí, takže pouzehandledEventsToo
naslouchací procesy mají možnost vyvolat další obslužné rutiny.
Tento koncepční návrh je posílen dříve zmíněným chováním směrování: je obtížnější (i když je to stále možné v kódu nebo stylech) připojit obslužné rutiny pro směrované události, které jsou vyvolány i v případě, že předchozí obslužná rutina podél trasy již byla nastavena Handled na true
.
Další informace o Handled, zpracování tříd směrovaných událostí a doporučení o tom, kdy je vhodné označit směrovanou událost jako Handled, viz označení směrovaných událostí jako zpracovávaných a zpracování tříd.
Vaplikacích Stále je ale vhodné označit směrovanou událost jako zpracovávanou v datech události, aby se zabránilo neočekáženým vedlejším účinkům pouze v případě, že prvek, který je dále v stromu elementu, má také připojenou obslužnou rutinu pro stejnou směrovanou událost.
Obslužné rutiny tříd
Pokud definujete třídu, která je nějakým způsobem odvozena z DependencyObject, můžete také definovat a připojit obslužnou rutinu třídy pro směrovanou událost, která je deklarovaný nebo zděděný člen události vaší třídy. Obslužné rutiny třídy jsou vyvolány před všemi obslužnými rutinami naslouchacího procesu instance, které jsou připojeny k instanci této třídy, kdykoli směrovaná událost dosáhne instance prvku ve své trase.
Některé ovládací prvky WPF mají vlastní zpracování tříd pro určité směrované události. To může dát vnější vzhled, že směrovaná událost není nikdy vyvolána, ale ve skutečnosti se zpracovává třídy a směrovaná událost může být potenciálně stále zpracována obslužnými rutinami instance, pokud používáte určité techniky. Mnoho základních tříd a ovládacích prvků také zveřejňuje virtuální metody, které lze použít k přepsání chování zpracování tříd. Další informace o tom, jak pracovat s nežádoucím zpracováním tříd a definováním vlastního zpracování tříd ve vlastní třídě, naleznete v tématu Označení směrovaných událostí jako zpracovávaných a zpracování tříd.
Připojené události ve WPF
Jazyk XAML také definuje speciální typ události označované jako připojená událost. Připojená událost umožňuje přidat obslužnou rutinu konkrétní události do libovolného prvku. Prvek, který zpracovává událost, nemusí definovat ani dědit připojenou událost, a ani objekt potenciálně vyvolá událost ani cílovou instanci zpracování musí definovat nebo jinak "vlastní" tuto událost jako člen třídy.
Vstupní systém WPF používá připojené události značně. Téměř všechny tyto připojené události se však předávají prostřednictvím základních prvků. Vstupní události se pak zobrazí jako ekvivalentní ne připojené směrované události, které jsou členy základní třídy elementu. Například podkladová připojená událost Mouse.MouseDown může být snadněji zpracována u libovolného daného objektu UIElement pomocí toho MouseDown , aby UIElement se místo zpracování připojené syntaxe událostí buď v XAML, nebo kódu.
Další informace o připojených událostech ve WPF naleznete v tématu Přehled připojených událostí.
Kvalifikované názvy událostí v XAML
Jiné použití syntaxe, které se podobá názvu typu. Syntaxe události připojená k události, ale není přísně řečeno použití připojené události je, když připojíte obslužné rutiny pro směrované události, které jsou vyvolány podřízenými prvky. Obslužné rutiny připojíte ke společnému nadřazení, abyste mohli využít směrování událostí, i když společný nadřazený objekt nemusí mít příslušnou směrovanou událost jako člena. Podívejte se na tento příklad znovu:
<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
<StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
<Button Name="YesButton" Width="Auto" >Yes</Button>
<Button Name="NoButton" Width="Auto" >No</Button>
<Button Name="CancelButton" Width="Auto" >Cancel</Button>
</StackPanel>
</Border>
Zde je naslouchací proces nadřazeného elementu, do kterého je přidána obslužná rutina StackPanel. Přidává však obslužnou rutinu pro směrovanou událost, která byla deklarována a bude vyvolána Button třídou (ButtonBase ve skutečnosti, ale k dispozici prostřednictvím Button dědičnosti). Button "vlastní" událost, ale směrovaný systém událostí umožňuje, aby obslužné rutiny pro všechny směrované události byly připojeny k libovolnému UIElement naslouchacímu procesu nebo ContentElement instanci, které by jinak mohly připojit naslouchací procesy pro událost CLR (Common Language Runtime). Výchozí obor názvů xmlns pro tyto kvalifikované názvy atributů události je obvykle výchozí obor názvů XMLNS WPF, ale můžete také zadat předpony oborů názvů pro vlastní směrované události. Další informace o xmlns naleznete v tématu Obory názvů XAML a mapování oboru názvů pro WPF XAML.
Události vstupu WPF
Jednou z častých aplikací směrovaných událostí v rámci platformy WPF je vstupní události. Ve WPF jsou názvy směrovaných událostí tunelování předponou slovem "Preview" podle konvence. Vstupní události často přicházejí ve dvojicích, přičemž jedna je událost bublající a druhá je událost tunelování. Například KeyDown událost a PreviewKeyDown událost mají stejný podpis, přičemž první událost je vstupní událost bublající a druhá událost je vstupní událost tunelového propojení. V některých případech mají vstupní události pouze verzi bublající nebo možná jen přímou směrovanou verzi. V dokumentaci témata směrovaných událostí křížově odkazují na podobné směrované události s alternativními strategiemi směrování, pokud takové směrované události existují, a oddíly na spravovaných referenčních stránkách vysvětlují strategii směrování každé směrované události.
Vstupní události WPF, které přicházejí ve dvojicích, jsou implementovány tak, aby jedna akce uživatele ze vstupu, například stisknutí tlačítka myši, vyvolala obě směrované události dvojice v sekvenci. Nejprve dojde k vyvolání události tunelování a jeho cesta. Pak se vyvolá bublinová událost a pojede její trasou. Dvě události doslova sdílejí stejnou instanci dat událostí, protože RaiseEvent volání metody v implementační třídě, která vyvolá bublající událost naslouchá datům události z události tunelování a znovu ji použije v nové vyvolané události. Naslouchací procesy s obslužnými rutinami pro událost tunelování mají první příležitost označit směrované obslužné rutiny událostí (nejprve obslužné rutiny třídy a obslužné rutiny instance). Pokud prvek podél trasy tunelování označil směrovanou událost jako zpracována, data již zpracovávaných událostí se odesílají pro událost bublání a typické obslužné rutiny připojené pro ekvivalentní vstupní události bublování nebudou vyvolány. Na vnější vzhled bude to, jako by obslužná bublinová událost nebyla ani vyvolána. Toto chování zpracování je užitečné pro řízení kompozitingu, kde můžete chtít, aby všechny vstupní události založené na hit-test nebo vstupní události založené na fokusu byly hlášeny konečným ovládacím prvku, a ne jeho složené části. Poslední prvek ovládacího prvku je blíže ke kořenovému adresáři v kompozitingu, a proto má příležitost zpracovat tunelovací událost nejprve a možná "nahradit" událost směrovanou událostí konkrétnější řízení, jako součást kódu, který backs the control class.
Jako obrázek toho, jak funguje zpracování vstupních událostí, zvažte následující příklad vstupní události. Na následujícím obrázku leaf element #2
stromu je zdrojem události i PreviewMouseDown
události MouseDown
:
Pořadí zpracování událostí je následující:
PreviewMouseDown
(tunel) v kořenovém prvku.PreviewMouseDown
(tunel) u přechodného prvku č. 1.PreviewMouseDown
(tunel) u zdrojového prvku č. 2.MouseDown
(bublina) u zdrojového prvku č. 2.MouseDown
(bublina) u přechodného prvku č. 1.MouseDown
(bublina) u kořenového prvku.
Delegát směrované obslužné rutiny události poskytuje odkazy na dva objekty: objekt, který vyvolal událost, a objekt, ve kterém byla obslužná rutina vyvolána. Objekt, ve kterém byla vyvolána obslužná rutina, je objekt hlášený parametrem sender
. Objekt, kde byla událost poprvé vyvolána, je hlášena Source vlastností v datech události. Směrovaná událost může být stále vyvolána a zpracována stejným objektem, v takovém případě sender
a Source jsou identické (to je případ kroků 3 a 4 v ukázkovém seznamu zpracování událostí).
Z důvodu tunelování a bublání nadřazené prvky přijímají vstupní události, kde Source je jedním z podřízených prvků. Pokud je důležité vědět, co je zdrojový prvek, můžete identifikovat zdrojový prvek přístupem k Source vlastnosti.
Obvykle, jakmile je vstupní událost označena Handled, další obslužné rutiny nejsou vyvolány. Obvykle byste měli označit vstupní události jako zpracovávané ihned po vyvolání obslužné rutiny, která řeší logické zpracování významu vstupní události specifické pro vaši aplikaci.
Výjimkou tohoto obecného prohlášení o Handled stavu je, že obslužné rutiny vstupních událostí, které jsou registrovány k úmyslné ignorování Handled stavu dat událostí, budou stále vyvolány na obou trasách. Další informace najdete v tématu Události verze Preview nebo označení směrovaných událostí jako zpracovávaných a zpracování tříd.
Datový model sdílených událostí mezi tunelovými a bublajícími událostmi a sekvenčním zvýšením prvního tunelového propojení a následným probuzením událostí není koncept, který je obecně pravdivý pro všechny směrované události. Toto chování je konkrétně implementováno tím, jak se vstupní zařízení WPF rozhodnou zvýšit a připojit vstupní páry událostí. Implementace vlastních vstupních událostí je pokročilý scénář, ale můžete se rozhodnout postupovat podle tohoto modelu i pro vlastní vstupní události.
Některé třídy se rozhodnou zpracovávat určité vstupní události, obvykle s cílem předefinovat, co konkrétní událost vstupu řízená uživatelem znamená v rámci tohoto ovládacího prvku a zvýšit novou událost. Další informace naleznete v tématu Označení směrovaných událostí jako zpracovávaných a zpracování tříd.
Další informace o vstupu a způsobu interakce vstupu a událostí v typických scénářích aplikace najdete v tématu Přehled vstupu.
EventSetters a EventTriggers
Ve stylech můžete do revizí zahrnout několik předem deklarovaných syntaxe zpracování událostí XAML pomocí značky EventSetter. Při použití stylu je odkazovaná obslužná rutina přidána do styled instance. Můžete deklarovat EventSetter pouze pro směrovanou událost. Například: Všimněte si, že b1SetColor
zde uvedená metoda je v souboru kódu.
<StackPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.EventOvw2"
Name="dpanel2"
Initialized="PrimeHandledToo"
>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<EventSetter Event="Click" Handler="b1SetColor"/>
</Style>
</StackPanel.Resources>
<Button>Click me</Button>
<Button Name="ThisButton" Click="HandleThis">
Raise event, handle it, use handled=true handler to get it anyway.
</Button>
</StackPanel>
Výhodou zde je, že styl pravděpodobně bude obsahovat velké množství dalších informací, které by se mohly vztahovat na libovolné tlačítko v aplikaci a mít EventSetter být součástí tohoto stylu propaguje opětovné použití kódu i na úrovni revize. EventSetter Také abstrahuje názvy metod pro obslužné rutiny o jeden krok dál od obecné aplikace a značky stránky.
Další specializovaná syntaxe, která kombinuje směrované události a animační funkce WPF je EventTrigger. EventSetterStejně jako u , pouze směrované události mohou být použity pro .EventTrigger EventTrigger Obvykle je deklarována jako součást stylu, ale lze ji EventTrigger deklarovat také na elementech na úrovni stránky jako součást Triggers kolekce nebo v ControlTemplatesouboru . Umožňuje EventTrigger určit Storyboard , která se spustí vždy, když směrovaná událost dosáhne prvku ve své trase, která deklaruje událost pro danou EventTrigger událost. Výhodou pouhého EventTrigger zpracování události a její příčinou spuštění existující scénáře je, že EventTrigger poskytuje lepší kontrolu nad scénářem a jeho chováním za běhu. Další informace najdete v tématu Použití triggerů událostí k řízení scénáře po jeho spuštění.
Další informace o směrovaných událostech
Toto téma se zabývá hlavně směrovanými událostmi z pohledu popisu základních konceptů a nabízí pokyny k tomu, jak a kdy reagovat na směrované události, které jsou již přítomny v různých základních prvcích a ovládacích prvcích. Ve vlastní třídě ale můžete vytvořit vlastní směrovanou událost spolu se všemi potřebnými podporami, jako jsou specializované datové třídy událostí a delegáti. Vlastník směrované události může být libovolná třída, ale směrované události musí být vyvolány a zpracovány UIElement nebo ContentElement odvozené třídy, aby byly užitečné. Další informace o vlastních událostech najdete v tématu Vytvoření vlastní směrované události.
Viz také
.NET Desktop feedback