do.Develop();

this.AreaOfInterest = Development.All();

Using the WeakEventManager in Windows Presentation Foundation

The problem

On my current assignment we got into some trouble in some of our usercontrols. Since this is a WPF application we make heavy use of binding data to our controls. We display some dates in a very common way and for this specific case we implemented a usercontrol for this. The usercontrol have two Dependency Properties for binding data to the control instance. When data is bound we call a method to populate the usercontrol.

An experienced WPF developer would notice that this is kind of a wierd way to handle this scenario since we could use templates instead. BUT there is also the possibility to bind different values to this control, so it is more of a dynamic usage-scenario which led us to use this approach. So, to keep this post still useful, let’s agree that this is the correct way of solving such a problem.

What happended in our case was that when the binding was created (or updated via INotifyPropertyChanged) a specific method was called. What eventually happened was that one developer didn’t know exactly how often this method was called, and put an eventhandler registration in there to listen for a static applicationevent of ours. Some of you may already understand what happened later on. There was NO code unregistering for this event. So, when the application started up, everything was fine. But when users started working with the application and the events started travelling across the system.

The _invocationCount of the event looked like this

You might think that this is not such a big deal because it will be disposed when the “parent” goes out of scope and that is true, but a static applicationwide event never will, as long as the application is alive (which was not as long in our case since the application died from an OutOfMemoryException :)).

Rebuilding the usercontrol was not really an option, but the good news is that there was another great solution to loosely couple the event registration in the usercontrol.

The solution

WPF introduces the WeakEventManger class in the System.Windows namespace. This class is added to support event registration that will not be a hard reference to its eventsource. The event delegation is done through an interface method instead of += delegate.

In the sourcecode for this post i have included two baseclasses that you can use (and the sample also makes use of them). One is for registering for static events and the other for events on an instance of an object.

What you need to do is create a WeakEventManager for each event that you want to support. Like this:

public class NewItemInViewModelListWeakEventManager : WeakEventManagerBase<NewItemInViewModelListWeakEventManager, ViewModel>
{
   protected override void StartListeningTo(ViewModel source)
   {
      source.NewItemInViewModelList += DeliverEvent;
   }

   protected override void StopListeningTo(ViewModel source)
   {
      source.NewItemInViewModelList -= DeliverEvent;
   }
}

Above is using the instance specific WeakEventManger baseclass. The generic arguments are the current eventmanager class and the instance type. This will attach the event through the manager instead of in the class that will handle the event.

Next up is just that class, the one that should handle the event.

Here we implement the interface IWeakEventListener. This interface contains only one method: ReceiveWeakEvent that will get called then the event is raised. It is here you place the logic that should occur if it does.

public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
   if (managerType == typeof(NewItemInViewModelListWeakEventManager))
   {
      var arguments = e as CustomerAddedEventArgs;
      lastAddedCustomer.Content = arguments.AddedCustomer.Id;
      return true;
   }
   return false;
}

When this is done you need to tell the manager that you are listening to events. This is normally done through the += delegate method. With the WeakEventManger, this is done like this:

   var viewModel = new ViewModel();
   NewItemInViewModelListWeakEventManager.AddListener(viewModel, this);

The smart thing about the WeakEventManger is, as i mentioned earlier, that it will create a loosley couple connection between the eventhandler and the source of the event. The WeakEventManger have a build in cleaning function. Since you register the listener with “this” it will have a reference to the class implementing IWeakEventListener and by that now where to distribute the event, but also have the possibility to locate finalized object and removing them from the distributionlist.

You don’t need to call the RemoveListener method (although it will help the managers cleaning pass a bit)

For us, this solution works very well and we can see that the GarbageCollector can finalize the objects and free up the memory.

The Sourcecode!

As always, have a look at the sourcecode and please get back to me with any comments or questions.

Download WeakEventPattern.zip

March 14, 2011 Posted by | Development, WPF | , , , | Leave a comment

ContextMenu bindings i WPF

Länk till källkod längst ner!

Om man i WPF använder sig av en ItemsControl (ListView, ListBox, GridView, etc), där man har bundit en ItemsSource till en lista av någon slag, så kan man inte använda sig av databindningar mot sin “huvud”-DataContext. När man befinner sig inne i en ItemsControl så är man enkelt förklarat på ett “CurrentItem” i den listan man presenterar.

För att då plocka upp en bindning mot sin huvud-ViewModel så måste man referera bindningen på ett annat sätt. Nämligen så här:

Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CurrentDateTime}"

Detta gör att bindningen letar uppåt kontrollens VisualTree tills den hittar typen Window och använder Path till att hämta ut DataContext (som i det här fallet är en ViewModel) och binder till ViewModel.CurrentDateTime.

När man sedan också använder ContextMenu inne i en ItemsControl så blir det lite mer komplext. En ContextMenu ligger i ett egen VisualTree (då den visas som ett lager ovanpå alla andra kontroller). Det man då måste göra är att använda sig utav PlacementTarget egenskapen på ContextMenu.

Det första man måste göra är att lägga till sitt datacontext objekt på Tag egenskapen på den kontroll som host-ar contextmenyn. Så här:

<Border Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}">

Det jag gör här är att binda upp Tag egenskapen på ett Border element till samma som formulärets DataContext (alltså min ViewModel instans).

Nu kan vi binda mot två stycken olika datakällor. Vi sätter DataContext på ett MenuItem till PlacementTarget sin parent (alltså ContextMenu). Mer förklarat blir det så att DataContext-egenskapen på ett MenuItem lokaliserar sin överliggande ContextMenu och sätts till PlacementTarget dvs en Border eftersom ContextMenu är placerat på ett sådant element.

Härnäst binder vi upp Header till DataContext.CaseDescription och eftersom vi är inne i en ItemsControl så kommer Border.DataContext vara ett currentitem ur listan vi visar upp.

Sedan binder vi ett kommando till ett kommando som ligger i ViewModel. Här använder vi då Tag.MsgBoxCommand. Tag i det här fallet refererar till Border.Tag som är vår ViewModel.

Vi skickar också med DataContext.CaseId som också kommer från currentitem.

<ContextMenu>
 <MenuItem Header="{Binding Path=DataContext.CaseDescription}"
 Command="{Binding Path=Tag.MsgBoxCommand}"
 CommandParameter="{Binding Path=DataContext.CaseId}"
 DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
 </ContextMenu>

Simpelt? Knappast. Men effektivt 🙂

Ladda ner ContextMenuBindings.zip källkod här!

May 5, 2010 Posted by | Development, WPF | , , , | Leave a comment

WPF och INotifyPropertyChanged

Ni som jobbat lite med WPF har med största säkerhet stött på interfacet INotifyPropertyChanged och varför man måste implementera det när man databinder sitt gränssnitt.
En kort förklaring är att WPF och Model-View-ViewModel förspråkar att man ska databinda sitt formulär/usercontrol till en ViewModel.
Därefter kan man då binda upp sina kontroller såsom textboxar, knappar osv mot properties i ViewModeln. Det som inte sker per automatik är att om man ändrar värdet på en property i ViewModel, så uppdateras inte gränssnittet automatiskt. Man måste skjuta av ett PropertyChanged event för att gränssnittet ska plocka upp det nya värdet.
En enkel lösning kan man tycka genom att bara fixa ett backingfield och i set{} skjuta eventet. Nackdelen är att man helt får glömma auto-properties (som jag själv är rätt förtjust i att använda). Det måste finnas en lösning på att låta detta ske automatiskt.
Så efter lite googlande hittade jag lite exempel och efter att ha samlat på mig lite info så kom jag fram till följande.

Genom att använda Microsoft Unity för att intercepta anrop till properties så kan man haka på lite funktionalitet när man kör propertyns set{}.
Det man måste göra för att få allt att ske per automatik är:

Eget attribut
Markera klassen (eller varje property individuellt) med ett eget attribut. I demon kallad NotifyPropertyChangedAttribute.

Properties som virtual
Markera varje property som ska användas vid databinding i gränssnittet som virtual.
Detta eftersom Unity använder sig av tre stycken interceptors (InterfaceInterceptor, TransparentProxyInterceptor, VirtualMethodInterceptor). Jag har valt att använda VirtualMethodIntercepter då jag i mitt nuvarande uppdrag har interface för varje ViewModel men har ingen lust att stoppa in alla properties i det och TransparentProxyInterceptor fungerade helt enkelt inte bra när man har både interface och registrerar dem och den konkreta klasses i Unity.

Instansiering
Man kan inte new:a upp en ViewModel utan måste resolva den genom en UnityContainer. På mitt uppdrag har jag löst det genom en ViewModelScanner som letar igenom en assembly efter klasser som har ett ViewModel-attribut och registrerar dessa i UnityContainern via en sådan här metod:

public static void  RegisterViewModel(Type  viewModel)
{
// Unity är en statisk instans  av en Microsoft.Practices.Unity.UnityContainer
Unity.AddNewExtension()
.RegisterType(viewModel)
.Configure()
.SetDefaultInterceptorFor(viewModel, new VirtualMethodInterceptor());
}

Sedan har vi en template i visual studio när vi skapar upp formulär/userkontroller som sätter databindningen i konstrukton till en resolve från Unity så här:

this.DataContext = ViewModelFactory.CreateViewModel<CarListViewModel>(this);

Det som sker nu är att när man sätter ett värde på en property så kommer set blocket automatiskt skjuta av ett PropertyChanged event. Detta event ligger samlat för alla ViewModel klasser på samma ställe, nämligen basklassen ViewModelBase. Man måste således inte implementera detta i varje ViewModel. CallHandlern för Unity’s interceptor traverserar uppåt i klasshierarkin och hittar ovanliggande event av typen PropertyChangedEventHandler.

Detta känns som mycket fluff för lite action men det är riktigt skönt att kunna använda auto-properties och bara låta sådant här fungera.

Ta gärna en titt på demo-zippen och återkom med frågor eller funderingar

Ladda ner WPF_PropertyChanged_Demo.zip källkod här!

February 22, 2010 Posted by | WPF | , , | Leave a comment