At work, my old boss would insist we programmatically assign and remove event handlers from our controls in the code behind, rather than simply double clicking a button (for example).
We'd have an AttachEvents() and DetachEvents() method on every single form. I don't remember his explanation as to why this is allegedly better than assigning it from the Design View, and he's since been transferred to a different project. My new manager doesn't know.
I thought he said it had something to do with events not properly being removed from memory, but I really don't know.
So: What is the benefit of doing it this way?
Performance-wise they are the same.
But doing it in the code behind is a much neater way since you control when to AttachEvents() or DetachEvents()
But you have to be careful in terms of avoiding any duplicate event wire ups. These in turn might lead up eating memory, but prominently they would cause performance issues since the event handler would be called as many times as it was wired up.
Some event handlers such as timers need to be removed before leaving a form otherwise they would still fire, for example
timer.Elapsed += ...
and
timer.Elapse -= ...
Probably a good and clear way to remember to do it in this way.
Other than the implications of your own architecture, there's no difference whatsoever.
The designer will place the event subscriptions on the InitializeComponent method and you should not do any changes to that method because the designer might override them or crash if it's something it can't handle.
Usually, the event subscriptions are events the form subscribes from its children. When the from is closed/disposed, all the children are disposed and each child will dispose event subscriptions.
Problems arise when the form subscribes to outside components. Then the form becomes "attached" to those components and, if not unsubscribed, becomes a resource leak.
There's also the possibility of events being fired when the form is not ready to handle them.
I've used a mixed approach where events from child controls were subscribed in the designer (or carefully manually coded in the InitializeComponent method) and used the AttachEvents/DetachEvents approach for components outside the UI (or the scope of the form/control).
so I have a control whose panel attaches these events inside the panel's initialized event:
gvvm = DataContext as GraphViewerViewModel;
gvvm.ZoomToFitEvent += new EventHandler(_GraphViewerViewModel_ZoomToFitEvent);
gvvm.ZoomInEvent += new EventHandler(_GraphViewerViewModel_ZoomInEvent);
gvvm.ZoomOutEvent += new EventHandler(_GraphViewerViewModel_ZoomOutEvent);
gvvm.CloseVCDEvent += new EventHandler(gvvm_CloseVCDEvent);
gvvm.LoadVCDEvent += new EventHandler(gvvm_LoadVCDEvent);
gvvm.ScrollToTimeEvent += new EventHandler<GraphViewerViewModel.ScrollToTimeEventArgs>(gvvm_ScrollToTimeEvent);
Question 1. When should I detach the events? Is is appropriate to do so in panel.unloaded?
question 2. Is it appropriate to use events to communicate from your view model to your view? it seemed more reasonable than creating a property bool and doing actions in the panel based on the propertychanged event, though that has the advantage of not requiring me to subscribe/unsubscribe events. But the downside is I have to think of reasonable names for a property event toggle.
Answer to question #1 is yeaaahhh, kinda, Unloaded event should serve for releasing resources.
However if the event handler is living only inside the control and you know that the control is not gonna be added or removed from VisualTree constantly during runtime then you could let the garbage collector do the job for you. Means once nobody holds the instance to your control the garbage collector will collect all of it anyways.
Answer to question #2: Read what Bernard said. The communication between View and ViewModel should not exist. However the ViewModel may communicate with the View which is the case everytime you set a Binding or you use INotifyPropertyChanged interface.
A common scenerio we are running into with our current application is where we need to route and event through several classes.
Here is a sample class heirarchy.
ActionManager
MainWindow
PresentationManager
MenuManager
Menu
MenuButton
The Menu subscribes to the click event of a MenuButton. It then creates a CustomAction object and raises an event that is subscribed to MenuManager. In the MenuManager event handler it in turn raises an event that is subscribed to by the PresentationManager, and so on.
Here is a sample of what is implemented for the PresentationManager:
void MenuManager_ActionGenerated(object sender, CustomActionEventArgs e)
{
if (ActionGenerated != null)
ActionGenerated(sender, e);
}
I was hoping that there would be a way that I could raise the event at the Menu level and receive it at the ActionManager level.
Is it bad practise what I am currently doing?
You can also look into Event Aggregator. A good example can be found at codeproject: Event Aggregator with Specialized Listeners
If what you've listed as your class hierarchy is actually your visual tree, it sounds like what you are describing is Routed events.
http://msdn.microsoft.com/en-us/library/ms742806.aspx
Personally, I get scared by having a lot of events. If you are not careful with unsubscription, they can extend the lifetime of your objects. Also, they may cause tight-coupling, reducing testability. In some cases using a Commanding pattern is a better approach.
I would try this CSharpMessenger Extended.
You can write your own SubscriptionManager.
By simplifying can be a Dicationary<string, List<Action<...>>>.
The key is the event-name, value is the List of Actions to run wen that even was raised.
So all yuor components subscribe to some specified event by adding its Action<..> to the list of specified event.
And when the even raised (always via SubscriptionManager) all Action<..>s from the list will be executed.
Just a basic idea. To make this production ready you need to code a bit more.
Good luck.
I'm making a MessageBox control in WPF using the MVVM pattern. This MessageBox will be used in multiple applications with different appearances, so ideally I want to keep code out of code-behind.
I'm trying to make the MessageBox appear when an event is raised, specified in the declaration of the MessageBox.
For example, this would be specified in the XAML of the window in which the MessageBox should appear.
<dialog:MessageBox
ShowOnEvent="EventRaised"
EventContext="{Binding}"
Message="I am a message box"
IconType="Warning"
ButtonsType="YesNo" />
The way this currently works: in the MessageBox ViewModel I'm using reflection to get the EventInfo for the event, then subscribing directly:
if (eventContext != null && showOnEvent != string.Empty)
{
EventInfo eventInfo = eventContext.GetType ().GetEvent (showOnEvent);
if (eventInfo != null)
{
eventInfo.AddEventHandler (eventContext, eventHandler);
}
else
{
Debug.WriteLine (string.Format ("Dialog: Couldn't find event {0} on {1}, check event name.", showOnEvent, eventContext));
}
}
This shows the MessageBox when the event is raised, as expected.
However, the event handler means that the MessageBox ViewModel is not GC'd when the main window's View is disposed. This means that if another view for the main window is created, another MessageBox is created, so if the event is raised, both MessageBoxs will show.
I tried getting around this by using a WeakEventManager, but the Weak Event Patterns documentation specify that an implementation of WeakEventManager should only handle one event - which means that I can't make a ShowOnEventEventManager with the event name as a string property and subscribe using that.
Does anyone have any ideas for the best way to go about this?
Having a weak event won't solve your problem because you won't be unsubscribed until the GC decides to run (unless you're explicitly calling GC.Collect()). As Will suggests in the comments, you can try to unsubscribe at the appropriate time or what might be even easier is just have your MessageBox check if it IsLoaded before showing itself.
I wouldn't worry about code-behind in your MessageBox unless you know of some reason why it would hurt its reusability. It's fine to have MessageBox code reference its view directly as long as the consumers of the MessageBox have a MVVM-friendly API.
The PRISM EventAggregator implements eventing using weak references by default. You need to be able to alter the code where events are published to implement this in your app.
There are proper code examples at the linked page as well as the obligatory flow diagrams. The event aggregator is fairly simple to use: you Publish with a strongly typed payload and Subscribe in as many places as you need. (And it's free to download)
I just came to realize, by reading some questions and answers on StackOverflow, that adding event handlers using += in C# (or i guess, other .net languages) can cause common memory leaks...
I have used event handlers like this in the past many times, and never realized that they can cause, or have caused, memory leaks in my applications.
How does this work (meaning, why does this actually cause a memory leak) ?
How can I fix this problem ? Is using -= to the same event handler enough ?
Are there common design patterns or best practices for handling situations like this ?
Example : How am I supposed to handle an application that has many different threads, using many different event handlers to raise several events on the UI ?
Are there any good and simple ways to monitor this efficiently in an already built big application?
The cause is simple to explain: while an event handler is subscribed, the publisher of the event holds a reference to the subscriber via the event handler delegate (assuming the delegate is an instance method).
If the publisher lives longer than the subscriber, then it will keep the subscriber alive even when there are no other references to the subscriber.
If you unsubscribe from the event with an equal handler, then yes, that will remove the handler and the possible leak. However, in my experience this is rarely actually a problem - because typically I find that the publisher and subscriber have roughly equal lifetimes anyway.
It is a possible cause... but in my experience it's rather over-hyped. Your mileage may vary, of course... you just need to be careful.
I have explained this confusion in a blog at https://www.spicelogic.com/Blog/net-event-handler-memory-leak-16. I will try to summarize it here so that you can have a clear idea.
Reference means, "Need":
First of all, you need to understand that, if object A holds a reference to object B, then, it will mean, object A needs object B to function, right? So, the garbage collector won't collect object B as long as object A is alive in the memory.
+= Means, injecting reference of Right side object to the left object:
The confusion comes from the C# += operator. This operator does not clearly tell the developer that, the right-hand side of this operator is actually injecting a reference to the left-hand side object.
And by doing so, object A thinks, it needs object B, even though, from your perspective, object A should not care if object B lives or not. As object A thinks object B is needed, object A protects object B from the garbage collector as long as object A is alive. But, if you did not want that protection given to the event subscriber object, then, you can say, a memory leak occurred. To emphasize this statement, let me clarify that, in the .NET world, there is no concept of memory leak like a typical C++ unmanaged program. But, as I said, object A protects object B from garbage collection and if that was not your intention, then you can say a memory leak happened because object B was not supposed to be living in the memory.
You can avoid such a leak by detaching the event handler.
How to make a decision?
There are lots of events and event handlers in your whole code-base. Does it mean, you need to keep detaching event handlers everywhere? The answer is No. If you had to do so, your codebase will be really ugly with verbose.
You can rather follow a simple flow chart to determine if a detaching event handler is necessary or not.
Most of the time, you may find the event subscriber object is as important as the event publisher object and both are supposed to be living at the same time.
Example of a scenario where you do not need to worry
For example, a button click event of a window.
Here, the event publisher is the Button, and the event subscriber is the MainWindow. Applying that flow chart, ask a question, does the Main Window (event subscriber) supposed to be dead before the Button (event publisher)? Obviously No. Right? That won't even make sense. Then, why worry about detaching the click event handler?
An example when an event handler detachment is a MUST.
I will provide one example where the subscriber object is supposed to be dead before the publisher object. Say, your MainWindow publishes an event named "SomethingHappened" and you show a child window from the main window by a button click. The child window subscribes to that event of the main window.
And, the child window subscribes to an event of the Main Window.
From this code, we can clearly understand that there is a button in the Main Window. Clicking that button shows a Child Window. The child window listens to an event from the main window. After doing something, the user closes the child window.
Now, according to the flow chart I provided if you ask a question "Does the child window (event subscriber) supposed to be dead before the event publisher (main window)? The answer should be YES. Right? So, detach the event handler. I usually do that from the Unloaded event of the Window.
A rule of thumb: If your view (i.e. WPF, WinForm, UWP, Xamarin Form, etc.) subscribes to an event of a ViewModel, always remember to detach the event handler. Because a ViewModel usually lives longer than a view. So, if the ViewModel is not destroyed, any view that subscribed event of that ViewModel will stay in memory, which is not good.
Proof of the concept using a memory profiler.
It won't be much fun if we cannot validate the concept with a memory profiler. I have used JetBrain dotMemory profiler in this experiment.
First, I have run the MainWindow, which shows up like this:
Then, I took a memory snapshot. Then I clicked the button 3 times. Three child windows showed up. I have closed all of those child windows and clicked the Force GC button in the dotMemory profiler to ensure that the Garbage Collector is called. Then, I took another memory snapshot and compared it. Behold! our fear was true. The Child Window was not collected by the Garbage collector even after they were closed. Not only that but the leaked object count for the ChildWindow object is also shown as "3" (I clicked the button 3 times to show 3 child windows).
Ok, then, I detached the event handler as shown below.
Then, I have performed the same steps and checked the memory profiler. This time, wow! no more memory leak.
Yes, -= is enough, However, it could be quite hard to keep track of every event assigned, ever. (for detail, see Jon's post). Concerning design pattern, have a look at the weak event pattern.
An event is really a linked list of event handlers
When you do += new EventHandler on the event it doesn’t really matter if this particular function has been added as a listener before, it will get added once per +=.
When the event is raised it go through the linked list, item by item and call all the methods (event handlers) added to this list, this is why the event handlers are still called even when the pages are no longer running as long as they are alive (rooted), and they will be alive as long as they are hooked up. So they will get called until the eventhandler is unhooked with a -= new EventHandler.
See Here
and MSDN HERE
I can tell you that this might possibly become an issue in Blazor. You can have a Component subscribing to events using the += syntax and in the long run, this will cause leaks.
The only solution to this (that I'm aware of) is to not use anonymous methods, have the Component inherit from IDisposable and use Dispose() to unsubscribe the event handler.