You can use
WeakEventManager +
IWeakEventListener to Remove EventHandler of Control before Remove Control. Else can Leak Memory
Finally call GC.
Note: Sample only to reference, when use Event 'click' in
WeakListternImp, it must a Action or delegate
Sample here: You can reference:
WeakEvent Any Event
file:MainWindow.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
namespace WpfApplication9
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var lis = new WeakListternImp{Name = "Click"};
WeakImp.AddHandle(button1, lis);
var lisc = new WeakListternImp { Name = "Checked" };
WeakImp.AddHandle(checkBox1, lisc);
var lis2 = new WeakListternImp { Name = "PreviewMouseDoubleClick" };
WeakImp.AddHandle(button2, lis2);
}
}
class WeakImp : WeakEventManager
{
static Dictionary<object,WeakListternImp> hold = null;
static Dictionary<object, Delegate> dele = null;
internal static void AddHandle(object source, IWeakEventListener handler)
{
if (hold == null)
{
hold = new Dictionary<object,WeakListternImp>();
}
hold.Add(source, handler as WeakListternImp);
Current.ProtectedAddListener(source, handler);
}
internal static void RemoveHandle(object source, IWeakEventListener handler)
{
Current.ProtectedRemoveListener(source, handler);
}
public static WeakImp Current
{
get
{
WeakImp man = GetCurrentManager(typeof(WeakImp)) as WeakImp;
if (man == null)
{
man = new WeakImp();
SetCurrentManager(typeof(WeakImp), man);
}
return man;
}
}
protected override void StartListening(object source)
{
Type ty = source.GetType();
var t = from x in source.GetType().GetEvents();
where x.Name == hold[source].Name
select x;
MethodInfo meinf = this.GetType().GetMethod("Active",BindingFlags.Instance| BindingFlags.NonPublic);
Type typehandler = t.First().EventHandlerType;
EventInfo eventinfo = t.First();
if (dele==null)
{
dele = new Dictionary<object, Delegate>();
}
dele.Add(source,Delegate.CreateDelegate(typehandler,this,meinf));
eventinfo.AddEventHandler(source, dele[source]);
}
void Active(object s, System.EventArgs e)
{
DeliverEvent(s, e);
}
protected override void StopListening(object source)
{
Type ty = source.GetType();
var t = from x in source.GetType().GetEvents();
where x.Name == hold[source].Name
select x;
MethodInfo meinf = this.GetType().GetMethod("Active", BindingFlags.Instance | BindingFlags.NonPublic);
Type typehandler = t.First().EventHandlerType;
EventInfo eventinfo = t.First();
eventinfo.RemoveEventHandler(source, dele[source]);
hold.Remove(source);
dele.Remove(source);
if (hold.Count == 0)
{
hold = null;
}
if (dele.Count == 0)
{
dele = null;
}
GC.Collect();
}
}
class WeakListternImp : IWeakEventListener
{
public string Name { get; set; }
public void click(object o, EventArgs e)
{
MessageBox.Show(o.ToString()+Name);
If(Name == "Click")
WeakImp.RemoveHandle(o, this);
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
click(sender, e);
return true;
}
}
}
file:MainWindow.xaml
<window x:class="WpfApplication9.MainWindow" xmlns:x="#unknown">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<grid>
<button content="click on" height="23" horizontalalignment="Left" margin="112,41,0,0" name="button1" verticalalignment="Top" width="75" />
<checkbox content="check on" height="16" horizontalalignment="Left" margin="116,115,0,0" name="checkBox1" verticalalignment="Top">
<button content="double click on" height="23" horizontalalignment="Left" margin="328,70,0,0" name="button2" verticalalignment="Top" width="120" />
Hope useful with you!