Mi sono trovato di fronte al prossimo malinteso.MouseButtonEventArgs.MouseDevice.DirectlyOgni equivoco
Preambolo:
ho wpf applicazione con i seguenti componenti essenziali: UI RadioButtons
e qualche controllo che utilizzano discesa basato su Popup
(in modo combobox). Secondo alcune logiche, ogni radio hook intercetta l'evento PreviewMouseDown
e fa alcuni calcoli. apre Nello scenario successivo,
- utente a comparsa (non selezionare qualcosa, pop-up solo restare aperto)
- utente clicca sul pulsante radio
PreviewMouseDown
non saranno licenziati per pulsante radio come previsto (a causa di Popup
feature).
E il mio obiettivo è sparare PreviewMouseDown
per RadioButton
nonostante uno.
tentativi di risolvere:
soluzione rapida e sporca è: Hook PreviewMouseDown
per Popup
e ri-fuoco PreviewMouseDown
evento con nuova fonte se necessario, utilizzando pulsante radio come sorgente. La nuova fonte può essere ottenuta tramite MouseButtonEventArgs.MouseDevice.DirectlyOver
. Il prossimo pezzo di codice farlo (evento è ri-licenziato solo se Popup
"mangiare" PreviewMouseDown
per click esterno):
private static void GrantedPopupPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var popup = sender as Popup;
if(popup == null)
return;
var realSource = e.MouseDevice.DirectlyOver as FrameworkElement;
if(realSource == null || !realSource.IsLoaded)
return;
var parent = LayoutTreeHelper.GetParent<Popup>(realSource);
if(parent == null || !Equals(parent, popup))
{
e.Handled = true;
var args = new MouseButtonEventArgs(e.MouseDevice,
e.Timestamp,
e.ChangedButton)
{
RoutedEvent = UIElement.PreviewMouseDownEvent,
Source = e.MouseDevice.DirectlyOver,
};
realSource.RaiseEvent(args);
}
}
Questo funziona bene quando sto allegando che gestore di Popup.PreviewMouseDown
direttamente tramite Behavior
e non funzionano (PreviewMouseDown
non viene licenziato per RadioButton) se sto allegando una via EventManager.RegisterClassHandler
(obiettivo è quello di evitare di attaccare il comportamento di ogni Popup
che possono occure a pagina con queste radiobuttons):
EventManager.RegisterClassHandler(
typeof (Popup),
PreviewMouseDownEvent,
new MouseButtonEventHandler(GrantedPopupPreviewMouseDown));
Il debugger ha mostrato che e.MouseDevice.DirectlyOver
(vedere il codice sopra) è Popup
, non Radiobutton
(come è stato quando ho collegato il gestore tramite Behavior
)!
Domanda:
Come e perché MouseButtonEventArgs
può essere diverso per la stessa azione, se EventHandler attaccata in due modi diversi?
Qualcuno può spiegare questo comportamento?
Grazie mille.
C'è un caso di test riproducibile minimo in XAML per questo per noi giocare? Potrebbe esserci confusione su cosa significa Anteprima nel contesto WPF. Come Anteprima * Gli eventi sono eventi di tunneling e potresti voler utilizzare l'evento MouseDown come per impostazione predefinita che ribolle il tuo albero visivo – Samuel
Puoi pubblicare XAML per il tuo Popup e RadioButton? Come ha detto Samuel, questo è un problema con gli eventi di tunneling vs bubbling. L'evento viene gestito sul Popup prima che possa raggiungere anche il Radiobutton è la mia ipotesi. –
Solo una pugnalata al buio, ma qualcosa di simile a questo lavoro? - Gestore di eventi MouseDown per popup => popup.Close(); Il gestore di eventi MouseUp per radiobutton => fai le tue cose. L'idea è che un MouseClick è costituito da due azioni, la prima azione MouseDown chiuderà il popup e la seconda azione MouseUp verrà catturata dal pulsante di opzione ... – Marko