How to distinguish between Sender and Source in WPF routed events - wpf

I would like to have a clear explanation about how to determine in each situation which control is the sender and which one is the source for a WPF Routed Event event both in the case of tunnelling and bubbling events.
Edit:
Suppose you have an event handler and two controls one child of the other. The handler is in the parent control. How would I know beforehand and without debugging which control is passed as the sender and which one as the e.source? And does this change when you consider bubbling or tunnelling events?The general concept of events is clear to me, but I would like to understand which parameter to use in the eventhandler to indentify both controls without debugging

There probably isn't an exhaustive "clear explanation", because there are so many ways you could end up with events. Especially when a lot of events use EventArgs.Empty, because there are no other details, other than the source.
http://msdn.microsoft.com/en-us/library/17sde2xt(v=VS.100).aspx
or, more specificly:
RoutedEvent: Source vs. OriginalSource
Do you have a specific question you need answered?
Edit: from the above linked article, with an answer similar to your comment
Consider a custom control (called CustomControl1 in this example) that is composed of a TextBlock.
When a MouseDown event is raised on the TextBlock, the OriginalSource property will be the
TextBlock, but in CustomControl1's handler, the Source will be changed to the CustomControl1
object so that other elements along the event's route will know that CustomControl1 received a
MouseDown.

Related

Call Methode from Event in XAML

Is it possible to have a UserControl with an Event (Event GoUp) that calls a Methode in an second Usercontrol (Sub Upgoing), and all this in WPF/XAML?
<controls:Joystick/> <!--with Event GoUp-->
<controls:TV/> <!--Sub Upgoing that should be called when Event GoUp is fired-->
I know how to solve this in Code Behind or ViewModel, but it is possible in XAML??
The short answer to your question is no. You cannot call methods in pure XAML.
You may hook up event handlers in XAML, but you'll still need to implement the event handler programmatically.
Also, if Joystick and TV are siblings in the element tree, an event raised from one of them won't bubble up or tunnel down to the other. A routed event either travels up or down, not sideways.

Events routing in WPF

I have implemented a UserControl. Then I would like to handle an event that is originally handled by Window (keyboard press). What is the best way to route the event caught by another component (higher in the components' tree)?
Thanks in advance for the replies and hints!
Cheers
It depends on the event you're trying to access. If it's a Preview event and the Window is setting e.Handled to true you'll need to use the method Alex suggests to circumvent the Window's handling of the tunneling. If it is a bubbling event (i.e. KeyDown) you don't need to do anything special since bubbling events hit the handlers on child elements first and go up the visual tree so the Window handler won't occur until after your UC's.
One thing you need to be careful with using Key events is that the event is only going to get picked up by your UC in the first place if the Focus is on or inside of it. This isn't something you need to worry about with things like Mouse events since they start at a specific location in the tree.
I believe you cannot gurantee that.
Window class is wrapping Win32 message-based event model and this will be the only WPF entity which will have access to those information.
I suggest that you create an attached property (which will be used by the Window) and implement the routing of the events yourself so that controls could subscribe to.
You can attach the routed handler specifying that you want to handle handled messages as well:
this.AddHandler(routedEvent, handler, true);
where this is an UIElement or derived class.
However there may still be events (key presses in this case) which don't make it past the window, not sure.

Some doubts in WPF

I am entirely new to WPF . Though I am going through the tutorials and articles from net but I am having doubts . Some of the questions which have striked out so far are
What is routed events and what extra thing it does server?
What are dependency properties and it's benefits.
How dependency properties differ from attached properties.
Why does first bubbling happens followed by tunneling? And what is the purpose of this?
e.g.
<canvas>
<button canvas.left=10/>
</canvas>
Is it a dependency property or attached property?
Thanks
Routed Event is event that design for tree of elements, when routed event raise it can travel up (bubbling) and down (tunneling) the element tree. For example if you have button inside grid, and you click button so route can raise up the tree to grid.
Dependency Property is another type of property that can notify when its value change, also it can inheritance and support multiple provider.
Attached Property is another form of dependency property that can attach to any kind of object. As I have slow, TextBlock.FontSize is attached property
<Canvas TextBlock.FontSize="10">
<TextBlock Text="Test" />
</Canvas>
Bubbling is for *_Changing event and tunneling is for *_Changed event. So if you need to validate and handle something you must use *_Changing event, if you validate by *_Changed event you may not handle (cancel) it.
In your example is attached property.
1 (& 4): Routed Events either bubble up or tunnel down the visual tree. And if someone sets "Handled = true" on the event args along the way then it goes no further. The point is, you don't know who in the visual tree will get the click event (e.g., a button might contain a StackPanel with an Image and a TextBlock...when the button is clicked the event could go to any of these), but with the Routed Event mechanism you have all the control you need over who should handle event. The convention is that Tunnel events have names prefixed with Preview (e.g., PreviewMouseDown is the tunneling version of the MouseDown bubbling event).
2: The thing about dependency properties is that they don't actually 'have' a value - the value at any point 'depends' on various other factors (such as: any styles, triggers, default values, etc). When several of these factors exist, there's an order of precedence which determines which value will be used...see here. This makes it easy to alter the display of an element (e.g., when the mouse is over it) and then change it back to whatever it was previously when the mouse is no longer over it, for example. The values for a dependency property can also be inherited from an ancestor - which is really useful for things like DataContext. So you can set the DataContext of an element and all of it's children will have access to it.
3: Attached properties enable a child element to store a value associated with a property on an ancestor. Like in the example you give the 'left' property belongs to the button's parent, the canvas. Attached properties mean that multiple child elements can store different values for the same property on the ancestor.
I hope this helps...keep digging and asking the questions - it's worth getting your head round this stuff!

Responding to a WPF Click Event in a Data-bound User Control

I hope this makes sense.
I have created several WPF User Controls. The lowest level item is 'PostItNote.xaml'. Next, I have a 'NotesGroup.xaml' file that has an ItemsControl bound to a List of PostItNotes. Above that, I have a 'ProgrammerControl.xaml' file. Each ProgrammerControl has a grid with four different NotesGroup user controls on it (and each NotesGroup contains 0-many PostItNotes.
Then, I have my main window. It also has an ItemsControl, bound to a list of Programmers.
So, you end up with a high level visual view of a list of programmers, each programmer has four groups of tickets, each group of tickets has many PostItNotes.
The trouble I'm having, is that I want to respond to a mouse click event in my mainWindow's code behind file.
I can add a MouseClick event into my PostItNote.xaml.vb file and that is getting called when the user clicks a PostItNote, and I can re-raise the event; but I can't seem to get the NotesGroup to listen for that event. I'm not sure if that's even the correct approach.
When the user clicks the PostItNote, I'm going to do a bunch of business-logic type stuff that the PostItNote control doesn't have a reference to/doesn't know about it.
Can anyone point me in the right direction?
You have a couple choices:
Use the PreviewXXX events which are fired during the "tunneling" phase of WPF event routing. The parent controls can always preview the events going down through them to children.
Use the more advanced approach to hooking up events leveraging the AddHandler method to which you can pass a parameter called "handledEventsToo" which basically means you want to know when the event happened "within" you even if some descendent element handled the event itself.
I am going to take a flyer here. You probably don't want to be handling the event that high up; not really anyway. You are catching the event at the lower levels, which is unavoidable. Consider invoking a routed command from the PostItNote click event handler.
The routed commands bubble up and tunnel down through the tree. You can have an architecture where a high-level handler can listen to a logical event (Opening a postit note perhaps?). The handler for this doesn't need to care where the command originates from. It might be from you clicking something, it might be from clicking on a toolbar button. Both are valid scenarios.
It sounds like you are creating some kind of custom UI, am I right? You want the application to respond to the users interactions. That is what the RoutedCommands are for.

How built-in WPF controls manage their event handlers to an attached event?

I know that when you register an object to the mouse's attached events, you have memory leaks. That's why you need to use WeakEvent pattern.
I have a problem with this pattern : If you want to use it, you cannot define your handler in the XAML code.
To me, it means that every code like this leaks :
<SomeControl Mouse.MouseDown="MyHandler" />
Unless you remove your handler explicitly in code (And I doubt that anybody does that).
Now there is something I don't understand :
<Button Click="MyHandler" />
This code somehow use somewhere the Mouse.MouseDown event to detect a click on the button.
With some research with reflector, I found that this event use MouseDown of the UIElement class. And when I read the code of UIElement I don't understand : there is no WeakEventManager !
Can someone can explain me how UIElement recieve events from Mouse.MouseDown without leak ?
Using normal handlers in XAML does not require weak references.
What you are doing is creating a memory reference between the main control and a child control contained within this control; the child control in this case is the button.
If someone maintains a reference to any part of the visual tree for the main control, the whole tree will stay in memory because it is linked together (parent/child references).
Now if all of the references to this tree are removed, the event reference between parent and child (the main control and the button) is not significant because these controls were already linked through parent/child references. Once all external references are removed, this control can be garbage collected.
Event handlers within XAML only create internal event references.
You have to be careful when external clients register to an event on a control, because you are creating an external reference that will keep the control alive as long as the link and the client exists (unless it is a weak reference).
Your question is about attached events. There doesn't appear to be any clear documentation on whether attached events cause memory leaks. It looks to me like the UI control that subscribes to the event contains a references to the event instead of the other way around, but I assume that the static event object must have some way of notifying the control that it has been fired. There appears to be a surprising lack of comment on this from Microsoft.

Resources