Putting the View in ViewModel – A ViewRegistry

One of the great things that MVVM has achieved is removing the dependency on the View in the ViewModel (Presenter). Occasionally, however,  I run into situations where I really need to know what View the ViewModel is associated with.

I need to create a dialog; which window is the owner? Or which control is the owner for pop-ups?

I want to change the Visual State with a call-back ; Which control do I pass to the VisualStateManager?

Having rejoiced that I no longer have a dependency on the View from my ViewModel, how do I get a reference to a ViewModel’s View?

The best solution I have seen thus far is the concept of a ViewRegistry. The ViewRegistry is dictionary of Views keyed by the View’s ViewModel. A View that knows it uses Dialogs or the VisualStateManager, for instance, registers itself with the ViewRegistry via an attached property. The ViewRegistry adds the View using it’s DataContext (the ViewModel) as the key. The View Registry handles the removal of unloaded views to ensure memory leaks don’t occur.

<UserControl pc:ViewRegistry.Register="true" ... >

It’s also good to note that a “View” can also be any control inside an actual view, this can be useful with things like the PopUp Dialog where you want the dialog to control a portion of a view.

  <Grid pc:ViewRegistry.Register="true" ... >

I shy away from ever injecting the ViewRegistry into a ViewModel, as this starts to bring back the coupling MVVM fought so hard to remove. Rather being viewy the ViewRegistry is used in more viewy services like the Dialog Service or Visual State Manager Service.

A View can be retrieved like this:

UIElement view = viewRegistry.FindViewFor(viewModel);

The ViewRegistry class is from Present.Core and can be viewed here.

Auto Mocking EventAggregator

A general rule about Unit Testing that I try to follow is that a change in the class under test should not break the test, unless the functionality under test is broken. It just makes things more maintainable.

For a long time, when I tested ViewModels I had a method called

StubEvent<TEvent, TPayload>()

This allowed me to stub all the required events for a test and control flow. However, when someone added a new event subscription or publication into the ViewModel,  the tests would fail as no one stubbed the new event; breaking the above rule.

The second problem when people started subscribing to Events on the UI Thread using

event.Subscribe(DoSomething, ThreadOption.UIThread);

The UIThread subscription uses Application.Current.Dispatcher which obviously isn’t there in most Unit Tests and so your subscriptions fail.

Enter AutoMockingEventAggregator; this bad boy returns a stubbed version of any event requested and adds a Dispatcher that can be used in testing. Just replace your mocked or concrete IEventAggregator with an instance of AutoMockingEventAggregator and all your testing woes are gone 😉
I even throw in a free AssertSubscriptionWasOnUiThread method.

AutoMockingEventAggregator.zip

On a separate note, if you aren’t committed/forced to use Prism’s EventAggregator, have a look at the Observable alternatives such as this one.

Accidental De-Virtualization

WPF’s UI Virtualization allows you to bind a large collection of data to a control without requiring the control to create a UI Element for each item in your collection. It does this by using Virtualizing Panels such as the VirtualizingStackPanel.

Recently I had a collection of 15,000 elements being bound to a ListView ( a different issue) and it was taking up seconds to do so!! After a frustrating performance search looking for rogue server calls on the UI Thread I opened up Snoop to discover 15,000 ListViewItems in my VirtualizingStackPanel; WTF?

There are a number of things that can disable the Virtualization of a control (this is not an exhaustive list of reasons why virtualization may not be working)

  • Not using DataBinding
  • VirtualisationMode, IsVirtualising, CanContentScroll properties set incorrectly
  • Grouping Enabled
  • Changing the ControlTemplate or ItemsPanel to a non-virtualizing panel
  • Not supported by the control

In my case, as verified by Snoop, my ListView was using a VirtualizingStackPanel. I had however overridden the wrong control template in order to get fixed headers and had rendered my virtualization moot. (By having my ItemsPresenter not being directly descendant of my ScrollViewer)

If your having trouble binding large sets of data, and you need to do it, ensure your using a Virtualizing Panel (and that there’s only a handful of items in it).

ComboBox Text

When you want to implement a required ComboBox, but don’t want to default the selection, the initial state of the ComboBox is empty.

How to display a nice message like “Please Select a Widget”?

I always start by setting the Text property, then rub my head as to why it isn’t displayed! The reason is that there is two ControlTemplates used by ComboBox; an Editable one and a non-Editable one. Only the Editable template uses the Text property.

Once you know this small tidbit, the rest is easy. Set IsEditable to true, Set IsReadOnly to True and set your text.

<ComboBox Text="Select An Item or Else!" IsEditable="True" IsReadOnly="True">
       <ComboBoxItem Content="Test 1"/>
       <ComboBoxItem Content="Test 2"/>
</ComboBox>

Note: if you are using a custom ItemTemplate, the selected item will not appear correctly. You should then set IsEditable to true in a trigger when there is no SelectedItem.

<Style TargetType="ComboBox">
  <Style.Triggers>
    <Trigger Property="SelectedItem" Value="{x:Null}">
	<Setter Property="IsEditable" Value="True" />
    </Trigger>
  </Style.Triggers>					
</Style>

VisualStateManager – Execute after Transition Finished

The VisualStateManager (VSM) is a class that allows you to define visual states (think Enabled, Disabled, MouseOver, Deleting, Saving) and programmatically move to those states.  (Part of WPF 4.0, for users of 3.5 you can get it as part of the WPFToolkit)

A great demo and walkthrough of using the VSM is here.

One of the draw backs of using the VSM has been the inability to be notified when the state transition has completed. For instance, say you wanted to animate the removal of an item from a ListBox i.e. some fancy fade and shrinking. You would create a Delete VisualState and when the user deletes you would transition to the Delete state and then remove the item from the list….. or would you?

Animations are kicked off by the VSM and control returned to the calling thread (it’s non-blocking). So in actual fact you will remove the item from the list before the animation really gets going and your databinding will remove the visual item from the ListBox without out all your fancy fade and shrink 😦

Enter PresentVisualStateManager, part of a wider demo (coming soon) of Present Fluent Commands. It allows you to execute an action after the animation has finished, by hooking into the StoryBoard Completed event
Classes are here:

A more MVVM friendly service is in the making but until then a control is passed into ChangeState (ala GotoState and GotoElementState), with the desired state name and an action to perform after the transition completes. ChangeState first calls GoToState (for Visuals defined in ControlTemplates) and if that fails to find the state it calls GoToElementState (for Visuals defined inline)

PresentVisualStateManager.ChangeState(grid, "Delete", () =>  this.itemsCollection.Remove(item.DataContext as ItemViewModel));

TemplateBinding – It’s sugar

When re-templating existing controls the TemplateBinding is your friend. It’s a way of getting user specified values for properties of the control and using them in your control template at runtime.

As in the example below we change a Label into a TextBox and use a TemplateBinding to set the Text of the TextBox to whatever the Content is of the Label.

<Label Content="Show me in a Label">
  <Label.Template>
    <ControlTemplate TargetType="Label">
      <TextBox Text="{TemplateBinding Content}" />
    </ControlTemplate>
  </Label.Template>
</Label>

However, if you try and bind to the Content of the Label you will notice that the source will never get updated with any changes typed into the TextBox/Label.
This is because TemplateBinding is really just syntactic sugar for the following:

{Binding Content, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}

So, if we want to do two-way TemplateBinding we just need to use the following binding instead of using a TemplateBinding.

{Binding Content, RelativeSource={RelativeSource TemplatedParent}}

Inheriting a DefaultStyle

This is mainly for me. I always forget how to do this and when ever I need it I can’t find it!

How do you specify a style for a control but still implement the default style for that control?

Add this line to your style definition (example for a button)

BasedOn="{StaticResource {x:Type Button}}"

WPF Fluent Commands

When writing a Command in WPF there can be a number of behaviours a command may need, to fulfil it’s purpose, which are actually orthogonal to the actual responsibility of the command (let’s say saving). For example the command may need to be scheduled (in the case of Auto-Save), it may need to “busy” the View, be executed asynchronously and ensure the current user has the authorisation to save the current item. Not only that, but the delete command and the load commands may also have to do the same things!

Present‘s Fluent Commands was born to enable the reuse of these common command decorations and allow the composition of commands using a fluent api.  (recently moved to Google Code)

The inner command (Save) is wrapped in a number of decorators each which add a single extra function to the inner command. Present currently has three Command Decorators

  • Schedule Decorator – Repeatedly executes a command every given time period.
  • Requery Decorator – Commands such as Prisms DelegateCommand rely on consumers to raise the CanExecutedChanged event to force the UI to reevaluate the CanExecute value of the command. This is not always feasible. This Decorator wires the CanExecutedChanged event to the CommandManager.RequerySuggested event so the CanExecute method is regularly re-evaluated.
  • Selectable Decorator – A decorator that exposes Properties the UI can use for binding “Selectability”.

More can easily be added, for instance internally we have a security decorator and a maximum concurrent executions decorator.

Scheduled Command

The second addition is Asynchronous behaviour. The AsyncCommand and CompositeAsyncCommand take AsyncActions which describes the life cycle of the operation and are executed using a BackgroundWorker.  The composite command allows for simultaneous asynchronous execution of multiple actions as well as an action to be executed when all actions have completed. Actions can also be decorated with extra behaviour such as the BusyAsyncActionDecorator which busys the View or the ObservableAsyncActionDecorator which turns the action into an Observable.

Async Command

Fluent Commands has now been released as part of Present (recently moved to Google Code).
A sample app can be dowloaded here.