Reputation: 2908
I've been trying to work with the mouse event handlers. Using MouseDown only seems to work with the right mouse button. And PreviewMouseLeftButton doesn't activate the MouseMove event until I release the left button.
So this code:
private void NewButton_MouseDown(object sender, MouseButtonEventArgs e)
{
var test = e.LeftButton;
var test2 = e.RightButton;
if (!bButtonIsDown)
{
bButtonIsDown = true;
Button mover = (Button)sender;
pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);
cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove;
cnvsLinkScreen.MouseUp += CnvsLinkScreen_MouseUp;
spMover = (StackPanel)((Button)sender).Parent;
pntPreviousPoint.X = Canvas.GetLeft(spMover);
pntPreviousPoint.Y = Canvas.GetTop(spMover);
}
}
private void NewButton_MouseMove(object sender, MouseEventArgs e)
{
Button mover = (Button)sender;
StackPanel spMover = (StackPanel)((Button)sender).Parent;
base.OnMouseMove(e);
if (e.LeftButton == MouseButtonState.Pressed)
{
// Inititate the drag-and-drop operation.
FindChild<StackPanel>(cnvsLinkScreen, "CSVImport");
pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);
Canvas.SetLeft(spMover, pntEnterPoint.X + 1);
Canvas.SetTop(spMover, pntEnterPoint.Y + 1);
}
}
Works but with right button only. When enabling the event handler with:
newButton.MouseDown += NewButton_MouseDown;
That event handler will not get touched with the left mouse button, which I think is odd.
I've done a good amount of reading out there and people refer to thePreviewMouseLeftButtonDown event handler but when I use that in place (same code) the cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove doesn't fire until I let go of the left mouse button (button up) then the StackPanel drags until I click and drop it.
I set breakpoints and see that the event handler is getting set, but it's just not working until after the left button is released. Clearly I'm missing something with the event handlers on this.
Why isn't the MouseDown event handler not even firing with a left mouse button down; only a right mouse button down?
Upvotes: 0
Views: 1778
Reputation: 6724
This has to do with Routed Events. Unlike with normal events, a routed event can be marked as handled, after which no further handlers for that event will be called.
MouseDown
and MouseMove
are bubbling routed events, meaning they start at the deepest elements (the ones inside the button) and then "bubble" their way up, through their parents, toward the Window
. Any parent can register a handler for these events and it will be called when the event reaches that parent's level. However if any child marks the event as handled, the event will never reach the parent and the parent's handler will never be called.
This is what's happening here. Button
has a handler for MouseDown
internally. When Button
decides it has been clicked, it raises its own Click
event and marks MouseDown
as handled. Button
also seems to handle MouseMove
, but only while a click is in progress. This is why your event handlers don't get called during a left-click, because left-click triggers a "click" which ends up handling those events before they make it out of the Button
.
PreviewMouseDown
and PreviewMouseMove
, on the other hand, are both tunneling routed events, meaning they start from the broadest parent (the Window
) and work their way inwards toward the exact point of the cursor. Tunneling events happen before bubbling events; the mouse input first tunnels in toward the cursor, then bubbles back up.
If you attach event handlers to PreviewMouseDown
and PreviewMouseMove
instead of MouseDown
and MouseMove
, you will see all the mouse input you expect.
Funny side note: you can actually play the same trick on Button
that Button
is playing on you. If you mark PreviewMouseDown
as handled before it gets inside the Button
, then it will never raise its Click
event.
Upvotes: 2