Today I saw a cool article on Code Project on how to do multi-binding in Silverlight using attached properties and a specialized type of value-converter. I though we could do the same thing with Value Converter Relays in nRoute.Toolkit without requiring additional classes/converters. So in this post we'll cover how to easily address multi-binding scenarios (as when you have multiple inputs, but one required output) using value-converter relays in Silverlight.

The Use-Case

The use-case is very simple, we have this form (shown below) that takes in a Person object with three properties namely Surname, First Name and Age - and as you enter them into the form, it updates the title of form with the full name derived from what you have entered. Nothing fancy, but the idea is that we should be able to consume two or more fields through one binding (as in multi-bind).

MultiBindingForm

Value-Converter Relays

Just to reiterate, a relay is like a facade to an actual implementation that can be specified elsewhere such as your code-behind or your ViewModel. In this case, we'll use a code-behind implementation as the requirement is essentially to turn two inputs into a formatted string, and that really is a view-level detail so it should stay there. All the same, if you wanted to use a ViewModel driven implementation then you can use a behaviour named  "BridgeValueConverterBehavior", which as you can guess "bridges" the relay with an implementation from your ViewModel (using bindings).

How-To Steps: Declare, Define and Use

Step 1, we declare the value-converter relay in our UserControl's resources collection, just like any static resource:

   1: <nComponents:ValueConverterRelay x:Key="TitleConverter"/>

Step 2, once we have the relay declared we define it in our code-behind. Here we are using an extension method available in nRoute.Components namespace that allows us to define the value-converter functionality using a lambda statement. Note, it is important to set this before we set the data-context, obviously because it is needed once the data-context is available.

   1: this.SetRelayConverter<Person, string>("TitleConverter", 
   2:     (p) => string.Format("{0}, {1}", p.Surname, p.Forename));

Step 3, to use the formatted string, we just bind to the data-context (which is the Person object) whilst using our value-converter relay:

   1: <TextBlock Text="{Binding Converter={StaticResource TitleConverter}, Mode=OneWay}"/>

And that's it we are done, we have our fake multi-binding in SL using value-converters. However, note there is one niggle, because we are directly setting the Person as our data-context, we have to manually update the data-context on the TextBlock whenever the property changes. This could be avoided by using ViewModels or INotifyPropertyChanged notifications, but since the original sample didn't I've avoided it too.

More Relays

Now that you've see the ValueConverterRelay in action, I'll just mention that we have two other types of relays in nRoute - one called Command Relay and another Value Relay. You can see a Command Relay in action in my recent ICommands related post, and the Value Relay is put to good use in my Web Xcel demo - there I've used it to "pseudo bind" to both a non-dependency property and also to another read-only dependency property. And so to sum it up, consider the use of relays for lot of sticky-stuff like pseudo multi-binding use, binding to data-templates, consuming read-only properties etc. and though it's not pretty it gets the job done.

You can download the value-converter relay project's source code,
note it requires the nRoute.Toolkit which is available on Codeplex,
and the original article on Multi-binding with source is available on Code Project.

Posted by Rishi on 11-Nov-09 2:01 PM, 12 Comments

Categories: nRoute, Silverlight

In a MVVM architecture ICommands are the primary abstractions that formalize the exposing and consumption of ViewModel defined functionality for use by its View. However, unlike WPF, Silverlight features no build-in ICommand implementations, supporting infrastructure or out-of-box integration with Controls. So, with this post I'll cover the ICommand-related infrastructure present in nRoute.Toolkit and go-over various aspects related to exposing, consumption and using ICommands in Silverlight.

1. Defining ICommands

Included in the nRoute.Toolkit are two ICommand implementations called ActionCommand<T> and ActionableCommand<T>, they both basically take in a delegate that handles the execution of the command. However, the difference between an ActionCommand<T> and the ActionableCommand<T> is simply that the latter allows you to define a delegated-based predicate that can determine as to if the command is currently executable. Also for convenience sake included are two non-generic versions of the same commands, that specifically relieve you of handling a command parameter.

ICommands

Also as shown above, the featured ICommand implementations provides you with an IsActive property using which you can enable or disable the command. Further, the RequeryCanExecute method allows you to re-evaluate as to if the current command is executable for its consumers. Further, to demonstrate a somewhat realistic use of an ICommand, we'll go-through a scenario from my Web Xcel demo app (shown below), whose code you can actually download from Codeplex.

WebXcel

For our use-case we are going to focus on a "Save Worksheet" functionality that is exposed as an ICommand via a property on the ViewModel. And the basic use-context is that we have this Worksheet Object (visualized as a Grid), which when changed can be saved by calling the "SaveWorksheet" Command, through the "Save Worksheet" Hyperlink Button (shown in the "Document Helper" panel above). Now, in the ViewModel code the SaveWorksheetCommand is declared and instanciated as follows:

   1: // Declare Command
   2: public ActionableCommand SaveWorksheetCommand { get; private set; }
   3:  
   4: // Define Command
   5: SaveWorksheetCommand = new ActionableCommand(() =>
   6: {
   7:     // basic check
   8:     if (this.Worksheet == null || !IsDirty) return;
   9:  
  10:     // update the status
  11:     var _token = StatusViewService.UpdateStatus(SAVING_WORKSHEET_STATUS);
  12:     SaveWorksheet();
  13:     _token.Dispose();
  14:    
  15: }, () => this.Worksheet != null && this.IsDirty)
  16: .RequeryOnCommandExecuted(OpenWorksheetCommand)
  17: .RequeryOnCommandExecuted(NewWorksheetCommand)
  18: .RequeryOnPropertyChanged(this, () => IsDirty);

In line 2, we declare a SaveWorksheetCommand property of type ActionableCommand, note it is the non-generic version and thus takes in no ICommand parameter. On initialization of the ViewModel, the ICommand implementation is instantiated as shown in Line 5. The constructor for the ActionableCommand takes in two parameters, one to define the execute functionality and second to define a predicated as to if the command is currently executable. So with Line 6-to-14 the execution handler basically updates the Status-Bar message (Line 11), then saves the active Worksheet via a helper method called "SaveWorksheet" (Line 12) and then retract the Status-Bar update (Line 13) by disposing the given token. Internally, the SaveWorksheet method serializes the Worksheet Object to a xml file and allows the user to save by showing a Save File Dialog. 

Also you can see in Line 8, we pre-check that the Active Worksheet to save is not null and that it has one or more pending changes (i.e. is dirty). That pre-check logic is basically the same logic that defines as to if we can execute the Save Worksheet command, and so in Line 15 the lambda statement defines the exactly same logic as the second parameter to the ActionableCommand constructor.

2. Defining ICommand Dependencies

As I hope is apparent, creating ICommands in your ViewModel is very straightforward but there is one aspect to that is rather cumbersome - the problem is that a command's execution is subject to a number of direct and indirect dependencies, and so whenever a dependency changes we must re-evaluated the current execution status of the command. In practical terms this means that dependencies should use the "RaiseQueryCommand" method to effect a CanExecuteChanged event, which tells an ICommand's consumers to check the executable status vis-a-vie the CanExecute method on the ICommand.

As you can image this is not only cumbersome but it also leads you to implicitly-defined ICommand dependencies throughout your code. So, with the nRoute.Toolkit's ICommand implementations we have a set of extension methods that you can use to explicitly define the dependencies, and using the same it also automatically updates any changes to the executable state of the ICommand. If this sounds fancy, it is not - lets look at our SaveWorksheetCommand example. In Lines 16-18 we explicitly define three cases that say re-query the executable status of the command whenever either of the OpenWorksheetCommand or NewWorksheetCommand commands are executed (because if we have just created or opened a Worksheet then there is nothing to save). And the third statement says that also re-query whenever the IsDirty property on "this" ViewModel changes (if Worksheet is Dirty, then the save status must have changed). So, now with these three extension methods the command's execution status is automatically re-evaluated, whenever either of the three explicit conditions occur.

Below is the list of the five included extension methods that help define dependencies on ICommands - however, do note you can write your own similar extension methods too (for more information, please see this post).

  • RequeryWhenExecuted - this methods basically says that whenever the command itself executes then re-query it's execution state.
  • RequeryOnCommandExecuted - as shown above, this one re-queries the command whenever some other command is executed
  • RequeryOnCommandCanExecuteChanged - this extension method says whenever the executable status of a another specified command changes then do a re-query
  • RequeryOnCollectionChanged - this pegs the re-query on a given collection changing, wherein the collection implements INotifyCollectionChanged
  • RequeryOnPropertyChanged - this extension as we have seen, begets a re-query when a INotifyPropertyChanged implementing object's property changes

ExecuteCommandBehavior 3. Consuming ICommands

As far as consuming ICommands is concerned, we are thoroughly-thoroughly covered by a so-named ExecuteCommandAction behaviour in the nRoute.Toolkit. And if you are wondering as why it is double-so-thorough, well because of three reasons besides the simple fact that it can execute commands. Reason one, even though the Silverlight framework itself does not support binding to Dependency Properties, with the ExecuteCommandBehavior you can bind to commands defined in your ViewModel - just remember you have to use the Binding post-fixed properties as shown in the Blend screenshot above. To know more about this so-called dual-property binding for Silverlight, please see my earlier post introducing nRoute.Toolkit. Similarly, you can also bind the parameter by using ParameterBinding property or alternatively statistically specify the parameter using the Parameter property.

Reason two, the execute command behaviour is implemented as a TriggerAction - what does that mean, it simply means you can pair it with any kind of Trigger (note, the Trigger and TriggerAction are from the Blend SDK). So the pairing can be done with an Event Trigger or a MouseWheel Trigger or a Gesture Trigger, in fact you can create your own trigger - like say one that responds to Voice Input. The benefit to all this Trigger-TriggerAction separation is that your use of a command is not limited to certain a set of pre-defined use-cases, which I think helps with both reusability and flexibility. So for example, with the SaveWorksheetCommand I've used the ExecuteCommandAction with two types of triggers.

   1: <!-- ICOMMAND WITH KEY STROKES -->
   2: <i:Interaction.Triggers>
   3:     <nTriggers:KeyTrigger WithControlModifier="True" Key="S" WithShiftModifier="True">
   4:         <nBehaviors:ExecuteCommandAction CommandBinding="{Binding SaveWorksheetCommand}"/>
   5:     </nTriggers:KeyTrigger>
   6: </i:Interaction.Triggers>

Above, we are pairing the KeyTrigger (for key-set Ctrl+Shift+S) with the ExecuteCommandAction behaviour that triggers the SaveWorksheetCommand in our ViewModel. And below we are pairing the same command behaviour with an EventTrigger to raise the command on a click event of a Hyperlink Button. Now, the XAML might look dreadful, but don't worry all this can be done visually in Blend - which will spit out the same XAML you see below.

   1: <!-- ICOMMAND WITH Click EVENT  -->
   2: <HyperlinkButton Content="Save Worksheet">
   3:     <i:Interaction.Triggers>
   4:         <i:EventTrigger EventName="Click">
   5:             <nBehaviors:ExecuteCommandAction ManageEnableState="True"
   6:                 CommandBinding="{Binding SaveWorksheetCommand, Mode=OneWay}" />
   7:         </i:EventTrigger>
   8:     </i:Interaction.Triggers>
   9: </HyperlinkButton>

4. Managing ICommand Control States

The third reason as to why the ExecuteCommandAction is thorough is that it allows you to control the enabled/interactivity state of the control it is applied on - by using the "ManageEnabledState" option (see the Blend screenshot above). What does that mean, it simply means that if the command's not executable it will disable the control for you - so for example in our SavewWorksheetCommand example, if there is no Active Worksheet or if the Active Worksheet is not dirty the Hyperlink Button will be disabled (see Line 5 in the XAML snippet above that enables this scenario by setting the ManageEnabledState to true).

WithPendingChanges NoPendingChangess

The picture on the left shows the Hyperlink Button disabled when there are no pending changes to the Active Worksheet, whereas the picture on the right shows an enabled Hyperlink Button when there are pending changes - the same is also indicated by the asterisks in the title. The enabling/disabling is done for you automatically (once you opt in the ManageEnabledState option), as the behaviour listens for changes in command's executable status and evaluates its use status against the command. Further, the ExecuteCommandAction behaviour also also plays nice with controls that don't have an IsEnabled (ie. non-Control type derived controls) property by taking away their interactivity. In the screenshot below, the Border Control doesn't support an IsEnabled property, however when the attached command is not executable the Border Control is dimed down and its interactivity is taken away.

ButtonVsBorderControl

5. Relaying ICommands

Now one of the other common problem you will find with ICommands is related to consuming it with templated controls like ItemsControl or ListBox Controls in Silverlight. The underlying issue is that from within a DataTemplate you can't access the ViewModel and hence the ICommands are not addressable. The reason is simple, because a DataTemplate's DataContext is set to the item being enumerated - so if a customer item is being enumerated, then that would be set as the active DataContext. So how do we solve this problem, the answer is simple - we first create a command relay as a resource in our View and then bridge the relay with an actual implementation from our ViewModel. Note, the command relay will be a static resource and thus can be "binded" as such.

Lets consider a simple example, lets say we have a ItemsControl that lists Customers collection from our ViewModel - it uses a DataTemplate that needs to consume an EMailCustomerCommand which is also defined in our ViewModel. So here is what we do, we first define an EMailCustomerCommandRelay in our View's resources collection and then use a BridgeCommand behaviour to source the relay from our ViewModel via Binding. Below is the relevant XAML:

   1: <!-- DECLARE RELAY -->
   2: <UserControl.Resources>
   3:     <nComponents:CommandRelay x:Key="EMailCustomerCommandRelay" />
   4: </UserControl.Resources>
   5:  
   6: <!-- BRIDGE THE RELAY FROM THE VIEWMODEL -->
   7: <i:Interaction.Behaviors>
   8:     <nBehaviors:BridgeCommandBehavior 
   9:         CommandRelay="{StaticResource EMailCustomerCommandRelay}"
  10:         CommandSourceBinding="{Binding EMailCustomerCommand, Mode=OneWay}"/>
  11: </i:Interaction.Behaviors>

Once we have done this, all we need to do is to use the CommandRelay in our DataTemplate as a StaticResource (see below). Also note we are passing the Active DataContext (which would be the Customer Object) as the Parameter to the ICommand:

   1: <DataTemplate x:Key="CustomerDataTemplate">
   2:     <StackPanel>
   3:         <TextBlock Text="{Binding CustomerName, Mode=OneWay}"/>
   4:         <Button Content="E-Mail Customer">
   5:             <i:Interaction.Triggers>
   6:                 <i:EventTrigger EventName="Click">
   7:                     <nBehaviors:ExecuteCommandAction 
   8:                         Command="{StaticResource EMailCustomerCommandRelay}"
   9:                         ParameterBinding="{Binding Mode=OneWay}"/>
  10:                 </i:EventTrigger>
  11:             </i:Interaction.Triggers>
  12:         </Button>
  13:     </StackPanel>
  14: </DataTemplate>

Now, remember this is all doable in Blend, so it's really quite simple once you get past declaring the relay and bridging the ICommand steps. For our sample scenario discussed above, you can download the Blend Project including the ViewModel part that is consumed by the CommandRelay.

Relay Commands in Blend

Summary

In summary, I've show how the ICommand related infrastructure in nRoute.Toolkit helps you to define, consume, manage and use ICommands in Silverlight. Further, given how central ICommands are to MVVM we have a feature-rich implementation that helps with both View and ViewModel sides of the divide, and also overcomes most of the platform-level shortcomings in Silverlight.

Download the nRoute.Toolkit from Codeplex
Download the Relay Command Project Source (note, require the toolkit dll)

Posted by Rishi on 03-Nov-09 8:28 AM, 26 Comments

Categories: nRoute, nRoute

In the first part I introduced nRoute.Toolkit as nRoute vNext sans Navigation and Composition components - whilst it lacks two of the key features, it introduces a boat-load of new features including Bindable Dependency Objects, Bindable Triggers, Actions and Behaviours for Blend, an IObservable-based Messaging Framework, Services component, View Services component, Modules component, ViewModel component and more. Extending that feature-set, in this post I'll cover some of the other more component-oriented features in the toolkit, like ICommand implementations, ICommand extensions, Weak Eventing handlers, Eventing extensions, and various Relays.

Action(able) ICommands

With regards to MVVM in Silverlight, I believe two interfaces carry a disproportionate share of the "architectural burden"  - with the two interface being ICommand and INotifyPropertyChanged. Both these interfaces bridge the chasm between the View and the ViewModel - one signifies an action occurrence, and the other signals a value change. Now, as far as the ICommand related functionality is concerned, they are well represented in the toolkit by two implementations named ActionCommand<T> and ActionableCommand<T>. Both of these implementations are actually refinements of what was earlier available in nRoute, however now they derive from a common interface called IActionCommand.

IActionCommands

With reference to the IActionCommand interface, the 'IsActive' property allows you to enable or disable the command, whereas the 'RequeryCanExecute' method allows you re-evaluate as to if the command can be executed, and CommandExecuted event is, well, quite self-explanatory. Both the ActionCommand<T> and ActionableCommand<T> support strongly-type parameters, and take in an Action<T> delegate to handle the command execution. The difference between Action and Actionable Commands is that the latter allows you to designate another delegate to determine as to if the command can be executed. Here's a simple example:

   1: // declared
   2: public ActionableCommand<string> SearchCommand { get; private set; }
   3:  
   4: // defined
   5: SearchCommand = new ActionableCommand<string>((s) => Repository.Search(s),
   6:                 (s) => !string.IsNullOrEmpty(s));

In the example above, we have defined a command that can take in a string value and uses it to search some repository. The command also defines a delegate that ensures that the search string is not null or empty before executing the command.

Now, as show in the class diagram, we also have non-generic versions of these commands that not only drop the generic parameter but also relieve you from having to process the same - so they ask for an Action delegate as opposed to Action<T>. I was surprised how useful these non-generic versions are, in my own use scenarios nowadays almost 95% of all of my commands are of the parameter-less variety.

Command Extensions

Very often you will find that a command's execution is dependent on some other factor, for example a delete command might be dependent on having something selected or like above a search command is dependent on the search-string being not null and not empty. Given a set of dependencies, a single change in any dependency requires us to manually re-evaluate a possibility of change in the executable-status of the command - specifically, with the IActionCommand interface, this is done via its RequeryCanExecute method (which inturn suggests this by raising its CanExecuteChanged event).

So, the point of the command extensions is to explicitly define dependencies which then can automatically trigger the possibility of a change in the executable-state of a command. I think the concept is easier described in code, have a look:

   1: var DeleteCommand = new ActionableCommand(
   2:     () => Repository.Delete(this.ActiveItem),
   3:     () => this.ActiveItem != null
   4: ).RequeryOnPropertyChanged(this, () => ActiveItem);

In the snippet above, the delete command allows us to delete the active item, where an active item is something that has been say selected in a ListBox. And the constrain on the execution of this command is that the ActiveItem property is not null, as shown in line 3. Now every time the selection of the ActiveItem changes, we must re-query the command's executable state - this intent is made explicit with the extension method shown in line 4. Here, the extension method exploits an INotifyPropertyChanged capable ViewModel (this) and listens for 'ActiveItem' property changes, which when changed triggers a re-query of the command's executable-state. Another version of this extension method exists that doesn't require a property name, as it listens to any/all property changes.

Similarly, we have another extension method that re-evaluates the executable-state after the command is executed. In the example below, the command's task is to set the count value to zero and therefore is only executable when the count is not zero. By using the RequeryWhenExecuted extension method we ensure that whenever the command is executed it's state is re-evaluated.

   1: var SetCountZeroCommand = new ActionableCommand(
   2:     () => this.Count = 0, 
   3:     () => this.Count != 0);
   4: SetCountZeroCommand.RequeryWhenExecuted();

There is another similar extension method called RequeryOnCommandExecuted which re-evaluates a command's status when another command is executed. So for example:

   1: // two commands
   2: SubscribeCommand = new ActionableCommand(() => { ... };
   3: UnsubscribeCommand = new ActionableCommand(() => { ... };
   4:  
   5: // explict dependencies
   6: UnsubscribeCommand.RequeryOnCommandExecuted(SubscribeCommand);
   7: SubscribeCommand.RequeryOnCommandExecuted(UnsubscribeCommand);

In the case above, the subscribe and unsubscribe commands' execution-states are re-evaluated when any of the other command is executed. Their respective execution-state is dependent on the whether or not a subject is subscribed or not. Another extension method called RequeryOnCommandCanExecuteChanged can re-evaluate a command by listening to another command's CanExecuteChanged event. However, you must be careful to not peg this extension method onto two commands re-querying against each other, as you will create an infinite loop between the two.

   1: // Declared
   2: public ActionableCommand CreateItemCommand { get; private set; }
   3:  
   4: public ActionCommand UndoCommand { get; private set; }
   5:  
   6: // Dependency Defined
   7: UndoCommand.RequeryOnCommandCanExecuteChanged(CreateItemCommand);

Lastly, we also have a RequeryOnCollectionChanged extension method, that can re-query a command when an INotifyCollectionChanged implementing collection changes. For example below, the command's execution status is dependent on the messages' collection having one or more messages, and so we make that explicit:

   1: ClearCommand = new ActionableCommand(() => Messages.Clear(),
   2:     () => Messages.Count > 0).RequeryOnCollectionChanged(Messages);

These extension methods work by pinging against the IWeakEventListener implementation that both ActionCommand<T> and ActionableCommand<T> support. Basically, the commands uses the ReceiveWeakEvent method to listen to any external suggestions that the command's execution-state might have changed, and so when pinged they raises the CanExecuteChange event to tell others to check their execution-status against the command. And as the interface name suggests, this is weakly/indirectly-referenced so you don't create leaking dependencies. Further, you can also use the same technique to attach explicit dependencies, using custom extension methods or just by making the command listen to any relevant event.

ExecuteCommandBehavior Execute Command Behavior

The ExecuteCommandBehavior does as it reads - with two notable features, one that both the command and command parameter are bindable. And second that it can enable/disable the usage of the associated element if ManageEnableState option is selected (see right).

The ManageEnableState option basically enables or disables a Control-type derived element, based on whether or not the command is executable. It listens to the CanExecuteChanged event and can re-evaluate the execution state of the command. Now, in the case where the element attached to the behaviour is not a Control-type derivative, it enables/disables the "interactivity" of the element - the interactivity concept is the same as one I mentioned in part one except here when the element is disabled we set the opacity to 50% (which might not be appropriate in all cases).

ManageEnableStateOption

The snapshot above shows the effect of the ExecuteCommandBehavior managing the enable state for you. The "Button Command" reading element is a button control (which is derived from the Control type), whereas as the "Border Command" reading element is a border element (not deriving from the Control type). In both the cases when the command cannot execute, they are non-responsive to user input - however as I've mentioned before there are limitations to how far the the interactivity approach will take you.

Weak / Event Handling

In another previous post I had detailed some of my ideas around weak eventing, with the crux of the idea being that by wrapping event handlers we could make the eventing infrastructure smarter without having to re-imagine the consumption or creation of events. And smarts give us the ability to weakly-reference the consumers, which makes the event consumer's lifetime independent of the event producers. Here's the how-to:

   1: source.SomethingHappened += new WeakHandler(Handle_Something, 
   2:     (h) => source.SomethingHappended -= h);  

In the snippet above rather than using an EventHandler delegate, we are using the WeakHandler class to handle the SomethingHappened event on the source object. The WeakHandler class implicitly creates the event handler, whilst lifting itself into the handler - and so it sits between the consumer and producer of event. By virtue of having a go-between we can do a lot of interesting things (as we'll see ahead), and so we also provide wrappers for normal handling (ie. non-weak) of the events. Secondly, by having this go-between we also gain the capability to allow consumption of events for non-delegate consumers - specifically, for IWeakEventListener and IObserver<Event<T>> based consumers. Consider:

   1: // using Listeners
   2: source.SomethingHappened += new WeakListener(weakEventListenerObj, 
   3:     (h) => source.SomethingHappended -= h);  
   4:  
   5: // using Observers
   6: source.SomethingHappened += new ObserverHandler(weakObserverHanderObj, 
   7:     (h) => source.SomethingHappended -= h);  

Also the IActiveCommand component mentioned above that makes uses of the WeakListener handler, similarly the Rx Framework makes use of Event to IObserver<Event<T>> translation for all its magic. Now, I'm not going to go into the depth of the eventing infrastructure, but basically there are six main classes - which allow for handling, listening, and observing of events in both strongly-referenced and weakly-referenced manners.

EventHandling

In all the classes above the type E generic parameter is an EventArg derivative associated with the event handler delegate of type H - for example to handle a size changed event for a Window the parameter E would be SizeChangedEventArgs and the associated parameter H would be SizeChangedEventHandler. To save you some time, there are some pre-defined wrappers available to handle common events based on EventHandler, EventHandler<E>, RoutedEventHandler and PropertyChangedEventHandler delegates. Also note all the given handlers are disposable - so when a handler is called upon to dispose it unregisters from the event and clears all references to the consumer/producer paving the way to be GC'ed.

Eventing Extensions

Like I said earlier, the idea with event handling wrappers was to introduce smarts in the consumption of events - and we have a number of smarts (beyond weak handling) available in the form of extension methods. Now, a lot of this would look like the Rx Framework which is by both by inspiration and design, but functionally it is quite different - here we have a pipeline model as opposed to an event stream model. And it works by the wrapper having pre-handling, post-handling and predicate-type gateways to the actual handling of the event. Also you can use these extensions whilst consuming an event via handlers, listeners or observers.

Handle When

   1: this.MouseEnter += new Handler<MouseEventArgs, MouseEventHandler>(
   2:         (s, e) => StartDragging(e),
   3:         (h) => this.MouseEnter -= h).
   4:     When(
   5:         (e) => e.EventArgs.StylusDevice.DeviceType == TabletDeviceType.Touch);

The When extension is simply a predicate to handling the event, and so when true it handles the event else it ignores the event call.

Skip When

   1: this.MouseLeftButtonUp += new ObserverHandler<MouseButtonEventArgs, MouseButtonEventHandler>(
   2:         _mouseButtonObserver,
   3:         (h) => this.MouseLeftButtonUp -= h).
   4:     SkipWhen(
   5:         (e) => _flagged);

The SkipWhen extension is the simply a negated version of the When predicated, therefore when true it skips the handling else it handles the event.

Handle Once

   1: Button1.Click += new RoutedHandler(
   2:         (s, e) => ProcessQuotation(),
   3:         (h) => Button1.Click -= h).
   4:     HandleOnce();

As the name suggests the HandleOnce extension ensures that you handle the event once and only once, it disposes off the handler post the first event. This is quite useful especially when you knowingly will only handle the event once, as in the case of loading or initialization, and with this extension you don't have to worry about unregistering the handler.

Handle Exactly

   1: LoginButton.Click += new RoutedHandler(
   2:         (s, e) => LoginUser(),
   3:         (h) => LoginButton.Click -= h).
   4:     HandleExactly(5);

HandleExactly extension will only handle the event a given number of times, thereafter it will unregister and dispose off the handler.

Handle While

   1: AuthorizeButton.Click += new RoutedHandler(
   2:         (s, e) => Authorize(),
   3:         (h) => AuthorizeButton.Click -= h).
   4:     While(
   5:         (e) => User.Session.IsAlive);

Keeping to its name, the While extension method handles an event while the given condition is true. If the condition turns false, it will unregister and dispose off the handler.

Handle Until

   1: AuthorizeButton.Click += new RoutedHandler(
   2:         (s, e) => Authorize(),
   3:         (h) => Authorize.Click -= h).
   4:     Until(
   5:         (e) => User.Session.IsAlive);

The Until extension is basically similar to the While extension, except that it allows for at least handling the event once. The While/Until terminology is akin to similarly-named operators in Visual Basic.

Handle For

   1: _model.PropertyChanged += new PropertyChangedHandler(
   2:         (s, e) => OnCountChanged(),
   3:         (h) => _model.PropertyChanged -= h).
   4:     HandleFor(
   5:         () => _model.Count)
 
The HandleFor extension method is specifically meant for PropertyChanged event handlers, as it allows you to explicitly handle a property changed event for a given property. Like in the example above it only handles the event when the Count property changes.
 
Throttle Handling
   1: this.DecreaseButton.Click += new RoutedHandler(
   2:         (s, e) => _viewModel.DecreaseCount(),
   3:         (h) => this.DecreaseButton.Click -= h)
   4:     Throttle(
   5:         TimeSpan.FromSeconds(5d));

The Throttle extension limits the handling the event to once per the given duration, so in the example above the handler will only be allowed to be executed once every five seconds from the execution of last event - with other calls within the same period being ignored.

Handler Timeout

   1: this.ConfirmButton.Click += new RoutedHandler(
   2:         (s, e) => _viewModel.Confirmed(),
   3:         (h) => this.ConfirmButton.Click -= h).
   4:     Timeout(
   5:         TimeSpan.FromSeconds(120), () => ConfirmButton.IsEnabled = false);

The Timeout extension awaits for event to occur within the specified time span, failing which the event handler is deregistered and the handler disposed off. Also you can specify an Action to be executed when the timeout expires. One benefit to this extension is that it brings the timeout semantics to any/all types of event.

Recurring Timeout

   1: this.KeyUp += new WeakListenerHandler<KeyEventArgs, KeyEventHandler>(
   2:         _dharmaInitiativeListener,
   3:         (h) => this.KeyUp -= h).
   4:     RecurringTimeout(
   5:         TimeSpan.FromMinutes(108), () => BlowupLostIsland());

The RecurringTimeout extension is basically like the Timeout extension except that every time the event occurs it resets the timeout and starts counting down again. Similarly, if the timeout were to occur the event handler is deregistered and the handler is disposed off, plus you can also specify a timeout Action delegate.

Lastly, note you can apply one or more of these extensions to a single handler, and equally you can create your own extensions for use with the given handlers in the toolkit.

Relays

My earlier post on relays, introduced IValueConverter and ICommand relays - building on that, we now have a ValueRelays and binding support for all relays types. Simply put, the point of relays is to act as a statistically declared go-between the actual implementation or value that is specified at runtime. The scenarios where this is useful is when you need to delegate the actual implementation/value from some other source such as a ViewModel or into something like a DataTemplate.

Value Converter Relay

Basically you use the ValueConverterRelay as a statistically declared resource that fronts an IValueConverter implementation defined at runtime. Statically, declaring a relay is as simple as:

   1: <nComponents:ValueConverterRelay x:Key="DateStringRelayConverter" />
 
Once the declaration is set, there are multiple ways to set the backing implementation. A direct way to set the implementation is to get the resource in your code-behind and set the converter.
 
   1: ((ValueConverterRelay)this.Resources["DateStringRelayConverter"]).Converter =
   2:     new ValueConverter<DateTime, string>((d) => d.ToString("DD, MMMM"));
 
To make the code-behind scenario a bit easy to use there are a couple of extension methods in the toolkit that allow you to set the resource-based relay declared with any FrameworkElement. So in the example below, we are setting the relay defined in the root level element's (this) resource collection:
 
   1: this.SetRelayConverter<DateTime, string>("DateStringRelayConverter",
   2:     (d) => d.ToString("DD, MMMM"));
 
Now, this approach for declaring and creating value converters is not an all-purpose solution, however for many simple cases and where the conversion logic is local to your use this compact approach helps. The other benefit of using relays is you can change the implementation at runtime, or as shown below you can have the value-converter's logic rooted in the larger logic of your ViewModel.
 
BridgeViewConverterBehaviorThe other way of defining a backing implementation for a value-converter relay is to bind the relay by bridging it. To do this, you can use the generously-named BridgeValueConverterBehavior type behaviour, and have it bind to any implementation like say from your ViewModel.
 
In the screenshot on the right, we have the ValueConverterRelay statistically bound to a local resource (show by the green rectangle), and the converter source is being feed from the ViewModel via binding (show by the yellow rectangle). And back in your ViewModel you can define the value-converter using the generic ValueConverter<TIn, TOut> wrapper class found in the nRoute.Components namespace.
 
   1: // declare
   2: public ValueConverter<User, string> UserNameConverter { get; private set; } 
   3:  
   4: // define
   5: UserNameConverter = new ValueConverter<User, string>(
   6:     (u) => u.LastName.ToUpper() + ' / ' u.FirstName + ' ' + u.Title);
 
Above the UserNameConverter is just a property in your ViewModel, which is sourced via bridging and consumed indirectly via the relay. Also notable is the fact that Silverlight doesn't support multi-bindings, so using value-converters like above can come in real handy.
 
Command Relay
 
I hope the name gives it away, but the CommandRelay is the equivalent of ValueConverterRelay for use with an ICommand implementation. Functionally, using and declaring them is similar to value converter relays, consider:
 
   1: <!-- Declared as a Resource -->
   2: <nComponents:CommandRelay x:Key="UpdateTimeRelayCommand" />
 
And to define the implementation in the code-behind, we can use an extension method like:
 
   1: this.SetRelayCommand<object>("UpdateTimeRelayCommand", (o) => UpdateTime());
 
Alternatively, we can also define the implementation by bridging the command using a BridgeCommandBehavior type behaviour available in the toolkit (note, in Blend you will currently have to use xaml to define the source of the command).
 
   1: <i:Interaction.Behaviors>
   2:     <nBehaviors:BridgeCommandBehavior 
   3:         CommandRelay="{StaticResource UpdateTimeRelayCommand}" 
   4:         CommandSourceBinding="{Binding UpdateTimeCommand, Mode=OneWay}"/>
   5: </i:Interaction.Behaviors>
 
In the case above we are sourcing the implementation of the command from the ViewModel. And one of the primary use scenarios of relayed commands is with DataTemplates in an ItemsControl. Since data templates are statically declared they are impervious to the data context of the View, and moreover their data context is set to the item being enumerated. In such a case, having them trigger commands in the ViewModel can be achieved via relays - so for example with the sample UpdateUserRelayCommand declared and bridged above, we can use it within a DataTemplate as such:
 
   1: <!-- Data Template declared as a Resource -->
   2: <DataTemplate x:Key="TimeInfoTemplate">
   3:     <Grid>
   4:         <Button Content="Update Time">
   5:             <i:Interaction.Triggers>
   6:                 <i:EventTrigger EventName="Click">
   7:                     <nBehaviors:ExecuteCommandAction 
   8:                         Command="{StaticResource UpdateTimeRelayCommand}"/>
   9:                 </i:EventTrigger>
  10:             </i:Interaction.Triggers>
  11:         </Button>
  12:     </Grid>
  13: </DataTemplate>
 
The Button in the DataTemplate above is rigged to raise a command when clicked - and using the bridge the command is ultimately trigged in your ViewModel. Now, having to first declare, bridge and then use the command may seem burdensome, but that speaks more to the shortcoming of Silverlight than to the solution for it.
 
Value Relay
 
A ValueRelay is again like before a statically declared facade for a value sourced at runtime - and its declaration as a resource is a simple as ever:
 
   1: <nComponents:ValueRelay x:Key="CurrentTimeRelayValue" />
 
And to source the value from a code-behind can be done as such:
 
   1: this.SetRelayValue<DateTime>("CurrentTimeRelayValue", DateTime.Now);
 
BridgeValueBehavior For bridging the value we can make use of the BridgeValueBehaviour type behaviour. It takes in the relay and provides it with a value as defined by either the ValueSource or ValueSourceBinding property (see right).
 
The ValueRelay implements INotifyPropertyChanged, which ensures that its consumers are updated whenever the source of the value changes. Also, as with the relays earlier, you can use this to convey some value to a DataTemplate from your ViewModel - which at times can be a lifesaver.
 
Now, the binding syntax to consume the value through a ValueRelay is slightly different than earlier - the main change being that we need to access the Value property of the ValueRelay to get the underlying value.
 
   1: <TextBlock Text="{Binding Value, 
   2:     Source={StaticResource CurrentTimeRelayValue}, Mode=OneWay}" />
 
Also, all relays support an Initialize event which at times is required, because depending on the use-case the resource-based relay should be available during the parsing of xaml, in which case the Initialize event can be used to setup the value - a previous post on relays details this scenario.
 
What's Next
 
The first release of nRoute specialized in View-level composition and navigation using Url-based routing. Now, as highlighted with this toolkit release, I've tried to include features that provide for Application-level composition using building blocks such as modules, services, view-services, loosely-coupled messaging etc. Additionally, I've also put in lot of infrastructure-level building blocks that tackle some of the bigger shortcomings in the platform like binding support, weak-eventing, relays, data-triggers support etc. With all the three-levels of concerns, the underlying intention is to make nRoute a more wholesome platform that extends beyond the self-defined application-flow role, to more-of a LOB framework designed for MVVM-oriented applications.
 
Based on that idea, the main highlights of the next drop of nRoute are dynamic application composition using SiteMaps, support for navigation to remotely defined resources, and a much improved Url-based Action infrastructure. Also I've written some extensions to RIA services for use with nRoute, that makes RIA services much more MVVM friendly whilst raising the level of abstraction of the Models provided by RIA Services. Put together, it should hopefully be a good starting point for any LOB application.
 

Posted by Rishi on 10-Oct-09 11:33 AM, 29 Comments

If you've done any amount of development with MVVM, one of the things you'll hate most is creating Value Converters and Commands for the smallest of things - especially for things like formatting, placement, visibility etc. And a lot of the times, these converters and commands are pertinent only to the View itself, but have to be declared on a module-wide basis. So as a solution, I've created "relays" for exposing IValueConverter and ICommand, which allow the logic to be defined in the code-behind (or ViewModel if you prefer), without having to create extraneous/individual classes.

Simple Example : Value Converter Relay

In one of my apps, I have a play/pause type of functionality which required a button to display either the play or pause sign, which is controlled by a "IsPlaying" property in the ViewModel. Now, the IsPlaying property is bool type, and we display the play/pause sign using the Webdings font in text. Normally, for this smallest of functionality, one would have to create an IValueConverter implementation and declare it in xaml, then consume it with binding. But with the relays we just declare a relay in xaml and then define the functionality in the code-behind, without having to create any specific class - have a look:

In XAML (with cmpnts being the xmlns declaration)

   1: <cmpnts:ValueConverterRelay x:Key="PlayPauseTextConverter" />

and in the code behind we write this

   1: this.SetResourceConverter<bool, string>("PlayPauseTextConverter", (b) => b ? ";" : "4");
 
and the button uses the converter, as usual
 
   1: <Button FontFamily="Webdings" Content="{Binding IsPlaying, 
   2:     Converter={StaticResource PlayPauseTextConverter}, Mode=OneWay}" />

Compared to the normal parade, this is much more immediate and compact - though for MVVM purists it might be polluting the code-behind. For my tastes, this works perfectly well and has a couple of advantages too - for one, it is strongly typed, allows lambdas/delegate based conversion, it enables referencing to and use of locally-scoped elements/variables and keeps the UI-related trickery close-by.

As far as the markup is concerned you declare every converter as ValueConverterRelay type, just with different keys. And then in the code-behind, using an extension method (on any FrameworkElement type, to which the resource belongs) or alternatively by directly setting the converter we specify the implementation logic. Note we can specify both "convert" and "convert back" IValueConverter calls equivalents using the SetResourseConverter extension method or equally specify a non-generic implementation.

Another Example : Command Relay

The companion to the converter relay, is the command relay type - and it is basically similar in declaration and use.

In XAML (with cmpnts being the xmlns declaration) we define a CommandRelay resource

   1: <cmpnts:CommandRelay x:Key="SelectContactCommand" />

and then in the code-behind something like

   1: this.SetResourceCommand<ContactInfo>("SelectContactCommand", (c) => OnSelectContact(c));

To consume the commands, as shown below, I'm making use of nRoute's attached behaviours to hook-in the commands to the user-control's MouseLeftButtonDown event

   1: <DataTemplate x:Key="ContactTemplate">
   2:    <view:ContactView cmd:MouseDown.Command="{StaticResource SelectContactCommand}"
   3:         cmd:MouseDown.CommandParameter="{Binding }"/>
   4: </DataTemplate>

Like before with the converter relay, we declare the command relay in the resources with a uniquely key which we then use to set the implementation in the code-behind - in this case using the SetResourceCommand extension method. Again note the command declaration is strongly typed, and makes use of the generic/delegate-based command implementations I had blogged about earlier.

As a side note, here I've purposely shown the command linking within a data template, because if you were to use a event handler hooked to the code-behind it could potentially leak memory - specially if the host control's life span outlasts that of the templated view (which is often the case, like when you are paging). And the difference in using attached behaviours, if designed properly, is that they hold a weak reference and should be GC'able.

One Complication

But then there is a twist; now, depending on how early in the control's lifecycle you make use of the converter/command, the relay might not be available immediately - particularly when the xaml is just parsed/initialized. And this is a big problem, because it means things would not work initially or worse they would "break" the databinding. In these cases we'll need to handle an "Initialize" event on the command or converter relay, during which we specify the implementation through the event argument - have a look:

In XAML, we hook up the Initialize event (and this shouldn't leak memory as resources normally last the entire lifetime of their hosts, unless you decide otherwise in which case you'll need to clear up any handlers)

   1: <cmpnts:ValueConverterRelay x:Key="CountToIndexConverter" 
   2:     Initalize="CountToIndexConverter_Initialize"/>

In the code-behind, we create and pass-back the converter through the event argument

   1: void CountToIndexConverter_Intitalize(object sender, ValueConverterInitializeEventArgs e)
   2: {
   3:    e.Converter = new ValueConverter<int, double>((i) => i == 0 ? 0d : i - 1);
   4: }

Obviously, this isn't ideal but as far as I know there is no precise way to interject between the resources creation and it's immediate use post-parsing of xaml - but resolving through an event handler works, and for the most part is more convenient than creating individual classes for each specific conversion or command you need.

Summary

So the basic idea here is to enable easy and compact defining and consumption of commands and value converters. However, it must be said, this is not a substitute for ViewModel based commands or general converters, rather my recommendation is to use it for consuming or manipulating visuals-related logic (as opposed to the business-related logic).

The code is attached below, and both these relays form part of the next drop of nRoute (which BTW has many new exciting ideas, stay tuned).

Download Code

Posted by Rishi on 25-Aug-09 9:06 AM, 9 Comments

Categories: nRoute, Code