Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using WeakEventManager with a static event

Is it possible to create a weak event listener on a static event using WeakEventManager?

I would like to create a weak event listener on the static CompositionTarget.Rendering event to avoid memory leaks when I don't know the lifetime of the WPF/Silverlight source element.

I implemented the rendering event manager by the weak event pattern:

public class RenderingEventManager : WeakEventManager
{
    public static void AddListener(IWeakEventListener listener)
    {
        CurrentManager.ProtectedAddListener(null, listener);
    }

    public static void RemoveListener(IWeakEventListener listener)
    {
        CurrentManager.ProtectedRemoveListener(null, listener);
    }

    private static RenderingEventManager CurrentManager
    {
        get
        {
            var managerType = typeof(RenderingEventManager);
            var manager = (RenderingEventManager)GetCurrentManager(managerType);
            if (manager == null)
            {
                manager = new RenderingEventManager();
                SetCurrentManager(managerType, manager);
            }
            return manager;
        }
    }

    protected sealed override void StartListening(object source)
    {
        CompositionTarget.Rendering += this.OnCompositionTargetRendering;
    }

    protected sealed override void StopListening(object source)
    {
        CompositionTarget.Rendering -= this.OnCompositionTargetRendering;
    }

    void OnCompositionTargetRendering(object sender, EventArgs e)
    {
        this.DeliverEvent(sender, e);
    }
}

and tested the manager in a simple window:

public partial class Window1 : Window, IWeakEventListener
{
    public Window1()
    {
        InitializeComponent();
        RenderingEventManager.AddListener(this);
    }

    bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
    {
        return true;
    }
}

The ReceiveWeakEvent method is not being called. OnCompositionTargetRendering is called, but it seems like DeliverEvent does not work as I expected. Adding listeners to instance events like Button.Click works fine... The test project is on .NET 4.0 Client Profile.

A post on Microsoft Connect from 2009 states that static events are not supported, but I checked the WeakEventManager source code, and it looks ok:

    protected void ProtectedAddListener(object source, IWeakEventListener listener) 
    { 
        Debug.Assert(listener != null, "Listener cannot be null");

        object sourceKey = (source != null) ? source : StaticSource;
        ...
    }
like image 245
objo Avatar asked Jan 16 '12 05:01

objo


1 Answers

Figured it out myself: change the sender argument of the DeliverEvent method to null:

void OnCompositionTargetRendering(object sender, EventArgs e)
{
    this.DeliverEvent(null, e);
}
like image 174
objo Avatar answered Sep 29 '22 23:09

objo