Warum wird das MouseDoubleClick-Ereignis des TreeViewItems per Doppelklick mehrfach ausgelöst?
XAML
<TreeView Name="GroupView" ItemsSource="{Binding Documents}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="OnTreeNodeDoubleClick"/>
</Style>
</TreeView.ItemContainerStyle>
....
</TreeView>
Code-Behind -
private void OnTreeNodeDoubleClick(object sender, MouseButtonEventArgs mouseEvtArgs)
{
Console.WriteLine("{3} MouseDoubleClick Clicks={0} ChangedButton={1} Source={2} Handled={4} ButtonState={5}",
mouseEvtArgs.ClickCount, mouseEvtArgs.ChangedButton, mouseEvtArgs.OriginalSource,
mouseEvtArgs.Timestamp, mouseEvtArgs.Handled, mouseEvtArgs.ButtonState);
}
Ich finde, dass für einen Doppelklick, der event handler mehrfach aufgerufen wird. Ich werde versuchen, öffnen Sie ein Dokument in der Registerkarte auf dem Doppel-klicken Sie auf den entsprechenden Knoten des Baumes; so würde ich benötigen, heraus zu filtern, die extra Anrufe.
23479156 MouseDoubleClick Clicks=1 ChangedButton=Left Source=System.Windows.Controls.TextBlock Handled=False ButtonState=Pressed
23479156 MouseDoubleClick Clicks=1 ChangedButton=Left Source=System.Windows.Controls.TextBlock Handled=False ButtonState=Pressed
In meine leicht-kompliziert-app, es wird gehoben 4 mal pro Doppel-klicken. Auf eine einfache repro-app, es wird gehoben 2 mal pro Doppel-klicken. Auch alle Ereignis-argument-Parameter sind die gleichen, also kann ich nicht unterscheiden, der Letzte Satz.
Irgendwelche Ideen, warum dies so ist, wie es ist?
InformationsquelleAutor der Frage Gishu | 2010-02-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich weiß, das ist eine alte Frage, aber wie ich über Sie kam in meine sucht nach der Lösung, hier sind meine Ergebnisse für alle zukünftigen Besucher!
TreeViewItem
s rekursiv enthaltenen gegenseitig.TreeViewItem
ist einHeaderedContentControl
(siehe msdn), mit der Kind-Knoten alsContent
. Also, jedeTreeViewItem
's Grenzen alle seine Kind-Elemente. Dies kann überprüft werden mit den hervorragenden WPF Inspector durch die Auswahl einesTreeViewItem
in der visuellen Struktur, die highlights der Grenzen desTreeViewItem
.In OP ' s Beispiel, der
MouseDoubleClick
- Ereignis registriert ist auf jedenTreeViewItem
mit dem Stil. Daher kann das Ereignis wird ausgelöst für dieTreeViewItem
s, dass Sie doppelt-klickte an - und alle seine übergeordneten Elemente - getrennt. Dies kann überprüft werden, in Ihrem debugger, indem Sie einen Haltepunkt in Ihrem double-click-event-handler und setzen eine Uhr auf der event-args' Source-Eigenschaft - Sie werden feststellen, dass es jedes mal ändert, wenn der event-handler aufgerufen wird. Übrigens, wie erwartet werden kann, dieOriginalSource
der Veranstaltung bleibt die gleiche.Gegen dieses unerwartete Verhalten, zu überprüfen, ob die Quelle
TreeViewItem
wird ausgewählt, vorgeschlagen von Pablo in seiner Antwort hat am besten funktioniert für mich.InformationsquelleAutor der Antwort Riaan
Wenn ein
TreeViewItem
doppelt angeklickt, wird das Element ausgewählt und als Teil der Steuerung des Verhaltens. Abhängig von dem jeweiligen Szenario, könnte es möglich sein, zu sagen:InformationsquelleAutor der Antwort Pablo
Ich habe einige debugging, und es scheint ein bug in WPF. Die meisten bereits gegebenen Antworten sind richtig, und die Problemumgehung ist, zu überprüfen, ob die tree-view-Element ausgewählt ist.
@ristogod s Antwort ist die am nächsten an der Wurzel problem - es wird erwähnt, dass die Einstellung
e.Handled = true
ersten mal-handler aufgerufen wird, wird nicht den gewünschten Effekt haben und die Veranstaltung weiter sprudeln, den Aufruf von parentTreeViewItem
s' - Handler (woe.Handled
istfalse
wieder).Der Fehler scheint zu sein, in der Sie diesen code in WPF:
http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Control.cs,5ed30e0aec6a58b2
Erhält er die
MouseLeftButtonDown
Ereignis (was wird behandelt, indem das Kind die Kontrolle schon), aber es schlägt fehl, um zu überprüfen, obe.Handled
ist bereits auf true gesetzt. Dann geht es zum erstellen einer neuenMouseDoubleClick
event args (mite.Handled == false
) und ruft, immer.Die Frage bleibt auch, warum nach setzen es behandelt die erste Zeit wird das Ereignis weiterhin Blase? Da in dieser Linie, wenn wir registrieren den handler
Control.HandleDoubleClick
:http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/Windows/Controls/Control.cs,40
passieren wir wahr, wie das Letzte argument, um
RegisterClassHandler
:http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/EventManager.cs,161
die
handledEventsToo
.Also die bedauerliche Verhalten ist ein Zusammenfluss von zwei Faktoren:
Control.HandleDoubleClick
heißt immer (für die behandelten Ereignisse auch), undControl.HandleDoubleClick
fehlschlägt, überprüfen Sie, ob das Ereignis schon behandelt wurdeIch benachrichtigt das WPF-team, aber ich bin nicht sicher, ob dieser bug ist Wert Festsetzung, da es möglicherweise brechen die bestehenden apps (die verlassen sich auf das aktuelle Verhalten der Ereignis-Handler aufgerufen wird, auch wenn
Handled
wurde auf true festgelegt, die von einer vorherigen handler).InformationsquelleAutor der Antwort Kirill Osenkov
InformationsquelleAutor der Antwort Denis Mandrov
Dies ist nicht wirklich ein brodelndes Problem. Ich habe das schon mal gesehen. Auch wenn Sie sagen, der Veranstaltung, die Sie behandelt, es weiterhin zu halten sprudeln. Außer, dass ich nicht glaube, dass es tatsächlich sprudeln, sondern feuern den Knoten aus, der über die eigene doppelklicken Sie auf Ereignis. Ich könnte Total falsch liegen. Aber in jedem Fall ist es wichtig zu wissen, dass zu sagen:
Tut nichts, um dies zu verhindern.
Einen Weg, um dieses Verhalten zu verhindern, ist zu beachten, dass, wenn Sie doppelt klicken, wird Ihnen zunächst ein einfacher Klick und die ausgewählte Veranstaltung sollte Feuer zuerst. So, während Sie kann nicht aufhören, die Double-Click-Ereignisse auftreten, sollten Sie in der Lage sein, zu prüfen, innerhalb der handler, um zu sehen, ob die event-Logik ausgeführt werden soll. Dieses Beispiel nutzt:
Manchmal muss man jedoch Situationen, in denen die Knoten ausgewählt werden, die von anderen Bohnen als über die TreeView-SelectedItemChanged Veranstaltung. In diesem Fall können Sie so etwas tun. Wenn Sie geschehen, haben ein TreeView mit einem einzigen deklariert obersten Knoten, können Sie geben, dass ein Knoten einen bestimmten Namen, und dann tun Sie etwas wie dieses:
Unabhängig von der Methode, die Sie verwenden, wichtig ist zu beachten, dass aus welchem Grund auch immer mit TreeViewItem Doppel-klicken, Sie kann nicht aufhören, die Ereignisse von feuern auf den Baum. Zumindest habe ich keinen Weg gefunden.
InformationsquelleAutor der Antwort Ristogod
Habe ich eine etwas elegantere Lösung als Kontrolle für die Auswahl oder die Erstellung flags:
Ein-Helfer-Methode:
Und dann den handler:
InformationsquelleAutor der Antwort Spook
Dies ist die wunderbare Welt des event-bubbling. Die Veranstaltung getanzt wird bis der Knoten-Hierarchie der TreeView und der handler wird aufgerufen, wenn für jeden Knoten in der Hierarchie-Pfad.
Nur so etwas wie
in der Prozedur code.
InformationsquelleAutor der Antwort banzai
Gibt es einige ziemlich große Probleme mit dieser Lösung, aber es könnte funktionieren, falls jemand braucht, um dieses problem zu lösen, die in mehreren Orten und ich habe ein Szenario, in dem die akzeptierte Lösung funktioniert nicht (Doppel-Klick auf eine Umschaltfläche klicken, öffnet sich ein popup, wo Sie die Anzeige-Taste im inneren ist ein weiteres element, Griffe doppelt klicken.)
{
private const string DoubleClickEventHandled = "DoubleClickEventHandled";
}
Verwenden DoubleClickEventHandlingTool.HandleDoubleClickEvent()
innerhalb der inneren/low-level element, z.B.:
Hoher Ebene-Doppelklick-event nur dann führt es die Aktion aus, wenn:
InformationsquelleAutor der Antwort Skychan
Ist der wahrscheinlichste Grund ist, dass die doubleclick-handler installiert ist, mehrere Male, so dass jede Instanz der handler wird aufgerufen, wenn für jeden Klick.
InformationsquelleAutor der Antwort John Knoeller