Safe event detachment base class for Windows Phone 7 behaviors


Some time ago I blogged about the Safe Event Detachment ‘pattern’ for behaviors and even included a snippet that made implementing this pattern easier. When I started to use this pattern more often myself I observed quite some code duplication appearing and I don’t like that. What’s more – although the pattern works well under Silverlight and WPF, there are some unique situations in Windows Phone 7 that need some extra attention – particularly the situation in which the user is navigating back to a page containing such a behavior. For when the user is navigation from the page, the AssociatedObject’s Unloaded event fires and the behavior is de-activated. If the user then moves back to the page – the AssociatedObject’s OnAttached event is not fired and the behavior is not re-initialized.
So I set out to create a base class taking care of most of this initalization hooplah without bothering the developer too much. This turned out to be not so simple as I thought. But anyway – thinks worked out. The initial setup of the base class is like this:using System;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
namespace Wp7nl.Behaviors
{
/// <summary>
/// A base class implementing the safe event detachment pattern for behaviors.
/// Optional re-init after page back navigation.
/// </summary>
/// <typeparam name="T">The framework element type this behavior attaches to</typeparam>
public abstract class SafeBehavior<T> : Behavior<T> where T : FrameworkElement
{
protected SafeBehavior()
{
IsCleanedUp = true;
}
/// <summary>
///Setting this value to true in the constructor makes the behavior
///re-init after a page back event.
/// </summary>
protected bool ListenToPageBackEvent { get; set; }
/// <summary>
/// The page this behavior is on
/// </summary>
protected PhoneApplicationFrame ParentPage;
/// <summary>
/// The uri of the page this behavior is on
/// </summary>
private Uri pageSource;
protected override void OnAttached()
{
base.OnAttached();
InitBehavior();
}
/// <summary>
/// Does the initial wiring of events
/// </summary>
protected void InitBehavior()
{
if (IsCleanedUp)
{
IsCleanedUp = false;
AssociatedObject.Loaded += AssociatedObjectLoaded;
AssociatedObject.Unloaded += AssociatedObjectUnloaded;
}
}
}
}
The comments already give away which direction this is going to take: the behavior keeps track of the page it’s on and that page’s uri to track if the user is navigating back to this page. If you don’t want this behavior, do nothing. If you need to track the user navigating back to the page (and believe me, in Windows Phone 7 you want that in most of the cases), set ListenToPageBackEvent to true in the behavior’s constructor. The setting up of this tracking is done in the next method:
/// <summary>
/// Does further event wiring and initialization after load
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void