WeakEventListener not detaching when NonShared ViewModel closes in Popup Region

Topics: Prism v4 - Silverlight 4
Sep 10, 2012 at 1:57 PM

Hi all, I'm hoping someone can help me...I'm struggling to get, what I think is, expected behavior using Silverlight Toolkit's WeakEventListener combined with Prism 4 & MEF.

I have a V/VM combination, marked as "NonShared". The view loads in a secondary region, almost identical to the way the StockTrader RI loads "News articles". I have 2 buttons on the view, "OK" and "Cancel", both of which should ultimately close the popup...which works. In the constructor for that view model, I use the Silverlight toolkit's WeakEventListener to hook up to the PropertyChanged event from my Model. I expect that when my View closes, my OnDetachAction would fire, but it does not. Here's some code to help explain my issue:


public class ZFlowBusinessManagementViewModel : ZFunnelDataEntryViewModel
    public ZFlowBusinessManagementViewModel(IZOpportunityController controller)
        : base(controller)
        _okCommand = new DelegateCommand(OKCommandExecuted, OKCommandCanExecute);
        _closeCommand = new DelegateCommand(CloseCommandExecuted);

        // Setup property changed handler for manufacturer estimate changes
        foreach (var estimate in MfrEstimates)
            /* hook up to property changed using weak event patten */
            var weakListener = new ZWeakEventListener<ZFlowBusinessManagementViewModel, ZSalesFunnelKeyMfrEstimate, PropertyChangedEventArgs>(this, estimate);

            estimate.PropertyChanged += weakListener.OnEvent;

            weakListener.OnEventAction = (instance, source, e) =>
                    // register handler
                    instance.estimate_PropertyChanged(source, e);

            weakListener.OnDetachAction = (listener, source) =>
                    // unregister handler
                    source.PropertyChanged -= listener.OnEvent;

            // ensure there is not reference to the weakListener
            weakListener = null;



Now, why when I close this view, I would expect the OnDetachAction to run, but it never does. Can anyone offer some advice?

Sep 10, 2012 at 6:07 PM


If you're using the behaviors provided in the Stock Trader RI to create your popup region, then I believe your problem could be related to how those behaviors work.

By default, neither the DialogActivationBehavior (which is the one that creates the popup) or the SingleActiveRegion (which is the type of region used for the popup) removes the view from the region; instead, they just deactivate it.

Based on my understanding, when a view is deactivated in a SingleActiveRegion applied to a ContentControl (which is the case of the popup implemented in the Stock Trader RI) it no longer appears in the ContentControl, but the region still holds a reference to it in its View collection. Therefore, as the view is not removed, it's being kept alive by the region, preventing it and its view model to be garbage collected.

If this is the cause of your problem, then a possible approach could be to implement the IRegionMemberLifetime interface in the ZFlowBusinessManagementViewModel. This interface defines a KeepAlive property which is checked by the RegionMemberLifetimeBehavior of the region when a view / view model is deactivated. If this property returns false, the aforementioned behavior will remove the view from the region automatically, avoiding this problem.

Please let us know if this approach is useful in your scenario.


Damian Cherubini

Sep 10, 2012 at 6:54 PM

Hi DCherubini, 

Thanks for responding. I am doing pretty much everything the same way as the Stock Trader RI (despite the fact that my V/VM in the popup is NonShared). So I tried your solution of implementing IRegionMemberLifetime. Unfortunately the Keep Alive property never gets hit when I put a breakpoint there. I follow the code through, and inside the DialogActivationBehavior, ContentDialogClosed(object sender, System.EventArgs e) is successfully called (and the region deactivates the content. I would have thought that right after that happens, the KeepAlive property would have been called...but it is not being called.

Do you have any suggestions as to how I could go about troubleshooting why the property isn't getting called?

Sep 10, 2012 at 8:46 PM


After further examination of the Stock Trader RI we found that the SingleActiveRegion that is created for the popup does not have Prism's default regions behaviors attached to it. Therefore, that regions doesn't have a RegionMemberLifetimeBehavior, which is why the KeepAlive property of your view model is never accessed.

A possible approach to solve this could be to modify the RegisterNewPopupRegion method of the RegionsPopupBehaviors class to add the aforementioned behavior after creating the region. For example:

public static void RegisterNewPopupRegion(DependencyObject owner, string regionName)
    . . . .

    region.Behaviors.Add(DialogActivationBehavior.BehaviorKey, behavior);

    // Adding RegionMemberLifetimeBehavior
    RegionMemberLifetimeBehavior rmlBehavior = new RegionMemberLifetimeBehavior();
    region.Behaviors.Add(RegionMemberLifetimeBehavior.BehaviorKey, rmlBehavior);

    regionManager.Regions.Add(regionName, region);

I hope you find this useful,

Damian Cherubini

Sep 10, 2012 at 9:05 PM

That seems to have done the trick. After looking at my setup a little more, I realized that I wouldn't have introduced any leaks since my model reference is local to my viewmodel, i.e. when my viewmodel is destroyed, so is my model reference. But with your help, I'm able to guarantee my viewmodel is being destroyed, which is what I was ultimately trying to do...so thank you!