Miałem do czynienia z kolejnym nieporozumieniem.MouseButtonEventArgs.MouseDevice.DirectlyOver nieporozumienie
Preambuła:
mam WPF aplikacji z najbliższych zasadniczych części Ui: RadioButtons
i pewną kontrolę które używają rozwijaną na podstawie Popup
(w combobox sposób). Zgodnie z pewną logiką każde zdarzenie z haczykiem radiowym wykonuje pewne obliczenia. W kolejnym scenariuszu
- Użytkownik otwiera okienko (nie wybrać coś, popup tylko pobyt otwarty) kliknij
- użytkownika na radiobutton
PreviewMouseDown
nie zostanie zwolniony za radiobutton zgodnie z oczekiwaniami (bo z Popup
feature).
I moim celem jest odpalenie PreviewMouseDown
dla RadioButton
pomimo jednego.
Próby rozwiązania:
szybki i brudny roztwór: hak PreviewMouseDown
dla Popup
i ponownego ognia PreviewMouseDown
zdarzenia z nowego źródła jeśli to konieczne, za pomocą radiobutton jako źródło. Nowe źródło można uzyskać przez MouseButtonEventArgs.MouseDevice.DirectlyOver
. Kolejny kawałek kodu to zrobić (zdarzenie zostanie ponownie zwolniony tylko jeśli Popup
„jeść” PreviewMouseDown
dla zewnętrznej kliknięcia):
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);
}
}
This prace dobrze kiedy jestem dołączenie tej obsługi do Popup.PreviewMouseDown
bezpośrednio poprzez Behavior
i nie działają (PreviewMouseDown
nie jest zwolniony za radiobutton) jakbym poprzez dołączenie jednego EventManager.RegisterClassHandler
(celem jest uniknięcie dołączenie do każdego zachowania, które mogą wystąpić maksymalnie Popup
na stronie z tych radiobuttons):
EventManager.RegisterClassHandler(
typeof (Popup),
PreviewMouseDownEvent,
new MouseButtonEventHandler(GrantedPopupPreviewMouseDown));
Debugger pokazał, że e.MouseDevice.DirectlyOver
(patrz powyższy kod) to Popup
, a nie Radiobutton
(jak to było, kiedy dołączam handler'a przez Behavior
)!
Pytanie:
Jak i dlaczego MouseButtonEventArgs
mogą być różne dla tego samego działania, jeśli Podprogram przymocowane na dwa różne sposoby?
Czy ktoś może wyjaśnić to zachowanie?
Wielkie dzięki.
Czy istnieje minimalna powtarzalny przypadek testowy w XAML za to dla nas grać? Może wystąpić zamieszanie związane z tym, co Podgląd oznacza w kontekście WPF. Jako Podgląd * Wydarzenia są wydarzeniami tunelującymi i możesz chcieć użyć zdarzenia MouseDown, ponieważ jest ono domyślnie propagujące twoje wizualne drzewo – Samuel
Czy możesz opublikować XAML dla swojego Popupu i RadioButton? Tak, jak powiedział Samuel, jest to problem z tunelowaniem vs bulgotami. Wydarzenie jest przetwarzane na wyskakującym okienku, zanim będzie mogło dojść do Radiobutton, to moje przypuszczenie. –
Po prostu pchnięcie w ciemność, ale czy coś takiego działa? - Obsługa zdarzeń MouseDown dla popup => popup.Close(); Obsługa zdarzeń MouseUp dla radiobutton => rób swoje. Pomysł polega na tym, że MouseClick składa się z dwóch akcji, pierwsza akcja MouseDown zamknie okienko wyskakujące, a druga akcja MouseUp zostanie przechwycona przez przycisk radiowy ... – Marko