The
OnMouseLeftButtonDownmethod marks theMouseLeftButtonDownevent as handled.
_Source: https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.button?view=netframework-4.8_
I guess many WPF programmers at one point will end up wasting time trying to figure out why the event MouseLeftButtonDown does not work on the Button control... I just wasted 30 minutes...
My suggestions is:
Button controlOnMouseLeftButtonDownAnother frustrated WPF programmer:
https://stackoverflow.com/questions/22813608/wpf-button-mouseleftbuttondown-doesnt-work-at-all
Random internet quote:
Oh My God! They Killed Button.MouseLeftButtonDown!
You bastards!
The current behavior seems right to me. The event is not meant to bubble up if a control acts on it (which the button does). This is exactly how I'd expect event bubbling to work. If this were to change, we'd get unexpected events on parent objects, which could trigger all sort of double-behaviors. Or put it another way: Changing this behavior would be a significant breaking behavior, and completely change what event bubbling is meant for.
If you want to override the bubbling, use the other subscribe approach which ignores event bubbling when setting handledEventsToo to true:
window.AddHandler(UIElement.MouseLeftButtonDownEvent, new RoutedEventHandler(MyMouseEventHandler), handledEventsToo: true);
You can also use the Preview* events as well.
Regarding this:
- Remove the event completely from Button control
It's an event inherited from the base-class that Button relies on.
- Mark the event as "You can't touch this"
You can touch this :-) Try subclassing and you can.
- Stop making standard events unusable by not setting the event as handled in OnMouseLeftButtonDown
This is RoutedEvents by design.
Reference doc:
The current behavior seems right to me. The event is not meant to bubble up if a control acts on it (which the button does).
The problem is that this button:
<Button MouseLeftButtonDown="LeftAction" MouseRightButtonDown="RightAction" />
acts on its MouseRightButtonDown event, but does not act on its MouseLeftButtonDown event... My first thought was that I may have handled the event somewhere else. I could not find anything when debugging, and first found the answer when I found the quote in the documentation... I don't think it's right that you have guess which events is working and which do not - and I do not think it's right that you must look it up in the documentation every time you are going to use another event handler. The event should at least somehow be marked as disabled...
I could understand that the MouseLeftButtonDown was not triggered if a Click event or Command was set up.
I'm not the first running into this problem - and I will not be the last if nothing changes.
I agree to @dotMorten that this is the behavior it should have. The Button marks the event as handled and raises its own Click event.
If you let the Mouse event bubble up, this will lead to other side effects. Think of a ListView where you created a DataTemplate for every item, and in that DataTemplate you've created a Button to delete the item. Now let's assume you've selected item 1, and you click the delete Button on item 2.
To me it makes sense as it is. And if you need the event, you can participate in the bubbling route by using the snippet @dotMorten has posted.
I agree the current design is correct but also that it can be confusing. If this was in C# (vs. XAML) this would probably be covered by either a Warning or an Analyzer. I wonder if there's something to be done in that realm for this class of problem?
Most helpful comment
The current behavior seems right to me. The event is not meant to bubble up if a control acts on it (which the button does). This is exactly how I'd expect event bubbling to work. If this were to change, we'd get unexpected events on parent objects, which could trigger all sort of double-behaviors. Or put it another way: Changing this behavior would be a significant breaking behavior, and completely change what event bubbling is meant for.
If you want to override the bubbling, use the other subscribe approach which ignores event bubbling when setting
handledEventsToototrue:You can also use the Preview* events as well.
Regarding this:
It's an event inherited from the base-class that Button relies on.
You can touch this :-) Try subclassing and you can.
This is RoutedEvents by design.
Reference doc: