My WPF app functions perfectly, but only when using a mouse. Troubles start when using it on a device with a touch screen..
I have a grid that handles MouseLeftButtonUp and TouchUp events.
Now, I press on the grid, it handles related events, then I press on some other control, that other control catches TouchUp event as expected, then TouchUp event is transformed into MouseLeftButtonUp event, which is also something to expect.
However, the newly fired MouseLeftButtonUp event is fired NOT for the control that I pressed on, but for the above mentioned grid! Why does it behave this way?
Thank you in advance...
This is normal behaviour for all RoutedEvents. From the UIElement.MouseLeftButtonUp event page on MSDN:
Although this routed event seems to follow a bubbling route through an element tree, it actually is a direct routed event that is raised and reraised along the element tree by each UIElement.
MSDN provides far more answers and far quicker than Stack Overflow.
Related
I wonder if D&D events not always firing (DragLeave/DragEnter).
I implemented a D&D feature in my WPF GUI. While dragging some element around I 'dragleave' a GUI element. Normally it fires an appropriate 'DragLeave' event, but not always. I fear, that for some speed reasons sometimes these events get not fired reliable. If that's the case, how can I overcome these issue?
Short Version:
I wrote some sample app to check it myself - and yes - the DragLeave event is not fired reliable.
Long Version:
What I did:
I placed a Label as a draggable object inside a StackPanel. Then I implemented the code for the MouseMove and DragLeave events. An additional TextBlock - added to the StackPanel as well - served as event output. If the DragLeave handler gets called, I changed the Text Property of the TextBlock to 'DragLeave occured'. Afterwards I tested it dragging the Label towards the StackPanel.
What I recognized:
If I was fast enough or pressed the mouse button close to the border of the Label, the DragLeave event was not fired. If I did it slow, everything worked fine as expected.
What I conclude:
I guess, if the mouse leaves the Label before the 'DoDragDrop' thread is initiated, the event is not fired, since the mouse is already outside the Label. So there is a small glitch between starting the D&D and the firing of the first event.
One can see the same behavior in the DragOver/MouseMove handler. The faster you move the mouse, the fewer points (e.GetPosition(...)) you can capture in the event handler.
Problem is, that for the DragLeave that missing event can be critical, since it is only fired once. However, the DragOver event is fired very often during a dragging and a missing event can be balanced by the next DragOver event directly afterwards.
I want to be able in my WPF application to detect the MouseUp event from anywhere. That is to say, if the user clicks in the control and holds his click, then releases it outside the Control, I want my MouseUp event to fire.
I have done the MouseDown event, it works, but the MouseUp event isn't fired if released outside the Window.
Add the CaptureMouse method in your MouseButtonDown handler
You can look up here on what it actually does.
Another way is using the windows API's for mouse_event described here:
Simulating Mouse Clicks
I would use the CaptureMouse listed above first but if that doesn't work for you this one should.
What is the exact difference between Bubbling Events and Tunneling events?
Where should I use Bubbling Events and where should I use Tunneling events?
WPF gives us a number of different mechanisms for handling events –
they are bubbling, tunneling, and direct. These are all known as
Routed events.
Direct event
You are probably already used to the direct routed event. This is
where the item itself handles the event that occurred. A good example
would be handling he onClick-event of a mouse button in standard
WinForms. This is where the event is raised in the GUI item and gets
handled by said GUI element.
Bubbling Event
Now we all like some bubbles in one form or another. Bubbling happens
when the event is not handled by the element ( say a textbox) and the
event "bubbles" its way up the UI containers which hold it. For
example, let's say you have a window that contains a panel and inside
that panel you have a grid and inside the grid you have a textbox. If
the event is not handled by the textbox, then it moves, is passed or
"bubbles" up to the grid level (as the grid contains the textbox), if
it is not handled at that level then the event bubbles further up the
"tree" (known as a visual tree) to the panel where it may or may not
be handled. This process continues until it is handled or the event
"escapes" the top most element.
Examples of a bubbling event would be something like a
MouseButtonDown event. Or a Keydown event.
Tunneling
Tunneling is the opposite of Bubbling. So instead of an event going
"up" the visual tree, the event travels down the visual tree toward
the element that is considered the source. The standard WPF naming
definition of a tunneling event is that they all start with "preview"
for example previewdownkey and previewmousebuttondown. You can
catch them on their way to the "target" element and handle it. An
example for this might be perhaps you have some controls inside a grid
control and for some reason you have decided that no control within
that grid will be allowed to have the letter "t" reach it.
Source with the opinion of the author which I don't support nor agree with.
And another StackOverflow question which is pretty much the same.
A nice demo project
And last but not least some explanation and another tutorial.
As a start: the naming convention in WPF for some default events is Preview<event> for tunneling and <event> for bubbling. So for example for the KeyDown we would have PreviewKeyDown and KeyDown, tunneling and bubbling respectively.
The difference between the two, as the naming convention implies, is that a tunneling event will start at the highest node in the tree (probably the Window) and going down to the lowest child. A bubbling event will start at the child and then go upwards again.
This guide should explain it clearly:
http://www.codeproject.com/Articles/464926/To-bubble-or-tunnel-basic-WPF-events
I am just going through the WPF concepts I came across these routed events ,dependency properties and attached events.
I think I am not able to understand the concepts behind them and why they were being called in the place of .net originated methods?
Routed Events provide the ability for different controls in the element tree to react to events.
For instance, if we have a Window containing a StackPanel containing a Button and someone presses the mouse key on the button, the events will be fired in this order:
PreviewMouseDown on Window
PreviewMouseDown on StackPanel
PreviewMouseDown on Button
MouseDown on Button
MouseDown on StackPanel
MouseDown on Window
These "preview" events use a behavior called Tunneling. The normal events Bubble up again.
If you set the Handled property of the EventArgs to true, the tunneling and bubbling will stop. Tunneling or Bubbling is called the Routing Strategy.
This enables handling a variety of situations, for instance:
Preventing any child element of the StackPanel to receive mouse down events. (Set Handled to true on StackPanel.PreviewMouseDown).
Handling key presses on a Window that have not been handled by any other control (Window.KeyDown)
I would advise not looking into Attached Events untill this becomes absolutely necessary. The scenario's for attached events are very limited. Attached events are also routed events.
I think I'm going crazy...
I have Canvas with event handlers for MouseMove & MouseLeftButtonUp.
However MouseLeftButtonUp is not being fired when it happens with cursor over TextBlock that is inside canvas.
(it fires just fine when I release mouse button in empty space of the canvas)
I tried attaching handler via AddHandler and using regular += syntax, nothing seems to work.
I tried using Canvas.CaptureMouse() but it doesnt seem to work either (CaptureMouse returns true btw).
MouseLeftButtonUp just doesnt want to propagate to it's parent when it happens over TextBlock (or any other element with IsHitTestVisible = true) inside Canvas.
Please help.
First I'd like to say that you are not going crazy. I've seen this before in Silverlight applications. Silverlight has some interesting event strategies. Silverlight events follow a bubble up approach for routed events but not with all events (msdn has some information on this) The events you are listening to are in that list but they are being handled by the TextBlock. Most UIElements have IsHitTestVisible=true so that mouse events and others are captured by the control and not bubbled up to its parent. Setting IsHitTestVisible=false should solve the problem. Other than that I can tell you what I have tried to overcome this issue when needing IsHitTestVisible=true.
Set the event hanlder from the parent on the TextBlock. Downside is you need to do this for every control in your canvas.
Try to fire the event through an extension class. I could not get this one to work cause i couldn't fire events using reflection.
You mentioned you tried AddHandler - did you try the AddHandler overload that accepts two parameters, the second one being "true" to indicate you want to get handled events as well?