Virtual Input Keyboard & Behaviours for Silverlight

Posted by Rishi on 09-Nov-09 9:04 AM - Comments (66)

You would already know this, but in Silverlight when in full-screen mode keyboard input is by design constrained to a limited set of keys - this often takes an end-user by surprise and leaves them with a perception than it's an application problem. To overcome this Silverlight limitation I've created a Virtual Input Keyboard and accompanying behaviours, that allows you to attach an on-screen keyboard to any receptive UI control.

VirtualInputKeyboard

View the demo app here.

The Input Keyboard

It is important to appreciate that the Silverlight Keyboard presented here is an Input Keyboard, which is different from a general purpose Virtual Keyboard found in most Operating Systems. The input keyboard is specifically only made visible on-screen when directly editing/inputting to an attached UI control (e.g. a TextBox), when not editing/inputting it is automatically hidden from view - this is very much like in mobile phones. So for example with the PasswordBox shown above the Input Keyboard will be made visible when the PasswordBox has focus, and in the "focus" state it allows you to "key-in" characters but anytime the PasswordBox looses the focus the keyboard also vanishes.

 K for Keyboard

Symbols Keys

Key Features

  • All character-keys feature iPhone'que callouts/popouts when pressed
  • A symbols mode (bottom right key) features most of the commonly used symbol and non-alphabetic characters (shown above) - however currently there is no support for customizing or appending custom symbols
  • There is a sticky shift-key (bottom left) that allows for capitalized alphabets
  • The keyboard also allows for a Title, above it is set to "User Password"
  • The keyboard is collapsable, see the arrow key show above (top right)
  • The keyboard is dragable, and is not constrained to its parent's bounds
  • The keyboard is based on the Popup Primitive in Silverlight, so it is not effected by z-index based layering
  • A single keyboard control instance can be registered and used throughout the application as the default keyboard
  • You avail the keyboard by attaching behaviours to UI controls, included are behaviours for attaching to a Textbox or a PasswordBox control
  • You can create custom behaviours to consume the Keyboard with other kinds of UI controls such as a Grid or ListBox (I will post separately about how to do this)
  • The behaviours also allow you to configure as to if the Keyboard is only available when in full-screen mode (the default setting)

Behaviours

Like I mentioned included are three behaviours based on the Blend SDK, which allow you the configure and attach the Keyboard with various UI controls.

ApplicationInputKeyboardBehavior

You put this behaviour onto an Input Keyboard, and it makes it the default application-wide keyboard for use by one or more UI controls. Without this, you'll need to specify onto each attached control the keyboard you want to use it. Further, to make life easy it has no configurable settings, so simply drag and drop this onto an Input Keyboard.

TextBoxInputKeyboardBehavior TextBoxInputKeyboardBehavior

This behaviour is applied onto a TextBox, and it in turn attaches a Keyboard onto it. Using this behaviours is very simple, it has three properties - one to specify the Title that is shown atop the Keyboard (note its use is optional). The second property, takes in the Target Keyboard name, as shown in the screenshot on your right. However, if you wanted to use the default application wide keyboard (as described above), then you leave this empty and it will resolve it automatically. Lastly, the VisibleInNonFullScreenMode property, allows the Keyboard to be visible when not in full-screen mode. Note again, the default behaviour will only show the keyboard when in full-screen mode, so turn this on if you want it available independent of the full-screen mode.

PasswordBoxInputKeyboardBehavior

As the name suggests this behaviour is applicable to PasswordBox controls, and the use API is identical to the TextBoxInputKeyboardBehaviour. However, the use-semantics are quite different - the TextBox keyboard behaviour can identify and use text-selection and cursor position information, and therefore the interaction with the Input Keyboard fully mimics the use-semantics we are accustomed too with a physical keyboard and mouse. Now, the PasswordBox control doesn't expose text-selection or cursor position information, which leads to somewhat counter-intuitive use interaction. For example, if you've partially selected some part of the password text and press a key with your physical keyboard it would overwrite the selection with the keyed character. However, with the Virtual Input Keyboard you can only append any keyed character to the end of the password string, because we are not party to selection or cursor-position information with the PasswordBox control. Also the automation API in Silverlight suffers from the same information deficiencies, which is why I've forgone its use.

Future Enhancements

Since this is just the first shot at this, there are plenty of possible enhancements. Some of the ones I am considering are:

  • Customizable key-sets, using predefined profiles - kind of like how iPhone offers a different key-set for entering Urls
  • An optional default action key, like one to trigger a "Google" - this is also akin to iPhones
  • Key press sounds option
  • Configurable relative positioning of Keyboard to any attached UI control
  • A numeric-pad version of the Input Keyboard, that only offers numeral characters
  • Templat'able Keyboard and Keys UI
  • A sharper/better default skin

If you have any other suggestions or ideas, do let me know.

You can download the Input Keyboard dll (16 kb) from the Expression Gallery Site,
and again you can view the demo app here.

UPDATE (17-Dec-09):

The following are two classes that allow you to attach the Keyboard to an AutoCompleteBox Control (found in Silverlight Toolkit). However do note that the AutoCompleteBox does not expose selection information so the keys are added and removed from the end of the text-string only - which unfortunately is not all that intuitive.

   1: // Keyboard Input Handler for AutoCompleteBox
   2: public class AutoCompleteBoxInputHandler : IInputKeyboardHandler
   3: {
   4:     
   5:     readonly AutoCompleteBox _autoCompleteBox;
   6:     
   7:     public event EventHandler InputKeyboardAttached;
   8:     public event EventHandler InputKeyboardDetached;
   9:  
  10:     public AutoCompleteBoxInputHandler(AutoCompleteBox autoCompleteBox)
  11:     {
  12:         if (autoCompleteBox == null) throw new ArgumentNullException("autoCompleteBox");
  13:         _autoCompleteBox = autoCompleteBox;
  14:     }
  15:     
  16: #region IKeyboardHandler Implementation
  17:     
  18:     public void KeyboadAttached() 
  19:     { 
  20:         if (InputKeyboardAttached != null) 
  21:             InputKeyboardAttached(this, EventArgs.Empty);
  22:     }
  23:         
  24:     public void KeyboardDetached() 
  25:     { 
  26:         if (InputKeyboardDetached != null) 
  27:             InputKeyboardDetached(this, EventArgs.Empty);            
  28:     }
  29:     
  30:     public void CharacterKeyed(Char character)
  31:     {
  32:         // we append to the end the added character, also notice there is no max length on auto-complete
  33:         _autoCompleteBox.Text = _autoCompleteBox.Text + character.ToString();
  34:     }
  35:     
  36:     public void BackspaceKeyed()
  37:     {
  38:         // we remove one letter from the end
  39:         var _existingText = _autoCompleteBox.Text;
  40:            if (_existingText.Length > 0)
  41:             _autoCompleteBox.Text = _existingText.Substring(0, _existingText.Length - 1);    
  42:     }
  43:     
  44: #endregion
  45:     
  46: }
  47:  
  48: // Behaviour Class to Attach to AutoCompleteBox
  49: public class AutoCompleteBoxKeyboardBehavior : InputKeyboardBehaviorBase<AutoCompleteBox>
  50: {
  51:     
  52: #region Override
  53:  
  54:     protected override IInputKeyboardHandler ResolveKeyboardHandler()
  55:     {
  56:         return new AutoCompleteBoxInputHandler(this.AssociatedObject);
  57:     }
  58:     
  59:     protected override void OnAttached()
  60:     {
  61:         base.OnAttached();
  62:         
  63:         // we attach to the textbox
  64:         AssociatedObject.GotFocus += new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
  65:         AssociatedObject.LostFocus += new System.Windows.RoutedEventHandler(AssociatedObject_LostFocus);
  66:     }
  67:     
  68:     protected override void OnDetaching()
  69:     {
  70:         base.OnDetaching();
  71:         
  72:         // detach the handlers
  73:         AssociatedObject.GotFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
  74:         AssociatedObject.LostFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_LostFocus);
  75:     }
  76:  
  77: #endregion
  78:  
  79: #region Handler
  80:  
  81:     void AssociatedObject_GotFocus(object sender, RoutedEventArgs e)
  82:     {
  83:         base.AttachToKeyboard();
  84:     }
  85:     
  86:     void AssociatedObject_LostFocus(object sender, RoutedEventArgs e)
  87:     {
  88:         base.DetachFromKeyboard();
  89:     }
  90:     
  91: #endregion
  92:     
  93: }

Also remember, you can create IInputKeyboardHandler implementation along with a matching Behavior for other types of input controls you require.

UPDATE (24-Apr-10):

Released Version 1.5 for Silverlight 4 - download from http://slik.codeplex.com
Also includes demo app's source code - which is also updated to SL 4.

Note, this release is build against System.Windows.Interactivity.dll from Blend 4 RC

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.
 

In the data world people often say that the database structure outlives any application consuming it, I suppose in the Web world it can increasingly be said that the Url will outlive any web application represented by it. In this context, nRoute is an attempt to make URLs a first class construct in Silverlight and WPF applications. Today, I've got the first release out on Codeplex, along with a sample application.

I am surely repeating myself, but below is the highlight of what is in the box today. I will go into details about each feature in a series of forthcoming posts that unfortunately will have to double-duty as some semblance of documentation, as does this post.

1. Routing Services: This is a direct port of the asp.net routing made available in .Net 3.5 release. However, in this case it deals exclusively in relative Urls and the semantics are changed in that it returns an IUrlResponse for a IUrlRequest send in.

Routing Services Overview

Normally you will not have to interface with the routing services, because you will consume services that build upon this.

2. Navigation Services: This deals exclusively in a navigation type requests/responses model that is usually consumed by some kind of a visual container. Just think of how the web works, you send a request, which is followed by a response that is consumed in a container (better known as a browser). Now, you don't really need a container to handle the response, you can consume it directly by using the NavigationService.

Navigation Services Overview
Again this is a bit low level plumbing you will normally deal with the NavigationService which is a static class and also with two build in IRouteHandler implementation that help serve the responses. The two handlers are NavigationRouteHandler and NavigationResourceHandler, let me show you the usage API for them:

// Navigation Route Handler usage
NavigationService.MapRoute(new Route("Customer/NewOrder",
    new NavigationRouteHandler(p => new DummyControl1(), u => (ISupportNavigationState)u)));

NavigationService.MapRoute(new Route("Customer/EditOrder/{OrderId}/",
    new NavigationRouteHandler(p => new DummyControl2(), u => (ISupportNavigationState)u)));

// Navigation Resource Handler usage
NavigationService.MapRoute("Images/MixLogo/", new NavigationResourceHandler("Images/MIX09Logo.xaml",
    NavigationResourceHandler.XamlLoader));

NavigationService.MapRoute("Images/2/", new NavigationResourceHandler("Images/iPhone2.jpg",
    NavigationResourceHandler.ImageControlLoader));
This is very similar to what is there is asp.net routing, basically all we are doing here is mapping an URL to a lambda expression that can initialize the responses on request. The second type of IRouteHandler shown above is the NavigationResourceHandler type, which basically makes it easy to materialize assembly resources as responses to any URLs like an image, text-file, or an xaml only file.

Again there is a higher level abstraction available for consuming the Navigation Services, please reference my forthcoming posts.

3. Action Services: This essentially is like a mapping for Urls to some handlers that work in the background. Think ICommands as a usage-model for this, basically you send in an ActionRequest that is handled by one or more IActionHandlers asynchronously off the UI thread. Usage scenarios include, fetching some data or processing some images all with the flick of an Url. Note, the action services do not produce a response, however they can issue some kind of response or signal once they are finished on the dispatcher thread.

Action Services Overview

This might seem quite weird but once you get a hang of it you will see how it really helps in usability and getting rid of the code-behind. The following is an example of registering an action and it's handler.

// We need to register an action url
ActionService.MapAction("Route 1", "Messenger/{MessengerType}/{ActionType}");

// and follow it up with by registering a handler for the action
ActionService.RegisterHandlerByRoute("Route 1", new MsnMessengerHandler());

// we can add another handler
ActionService.RegisterHandlerByRoute("Route 1", new GTalkMessengerHandler());
Here we register an action Url, we follow it up by registering two handlers that respond to the action call. Yet again, there is a higher level abstraction available for consuming the Action Services.

4. Navigation State Management: One of the thing the web is fraught with is state management (just see how bulky Viewstates can become or how complex forms handling can be), but they are core to the navigation experience that the web offers. Everyone is now familiar with back and forward semantics and my attempt to capture that is with these three interfaces:
StateSupportOverview

Ideally you will implement these interfaces in your ViewModel and when registering your Url handler you will point to how we can extract/get the ISupportNavigation interface. Note, it's use is optional.

5. Navigation Containers: When we navigate we do so in a container, and that is what these quintessentially are. However, they play the very important role of modelling different ways to navigate like a browsing with back-forward capabilities or navigating onwards only. I have four containers built in, shown below.


NavigationContainersOverview

The four objects to your right, are actual usable visual controls that reflect the models onto their left.  Below is a summary of the behaviour exhibited by the four controls:

  NavigationContentControl This is a vanilla and light-weight content control that can handle a navigation response and that's it. It offers no navigation history, events or related behaviour. Think Vanilla Light.
  NavigationContainer This is also a plain control that inherits and extends the NavigationContentControl but offers a richer model with events and hook ups at the application level. However, it stores no history, state or anything and it plainly navigates from one url to another. Think Direct and Onwards.
  BrowsingContainer This builds on the NavigationContainer and offers a web-like behaviour and state management features. So it stores a stack of back pages history and states it has been to and the forward pages you've backed-up on. Plus, like a browser the state is only stored for back or forward pages, and opening a new pages initializes a new state. Think Very Web-Like.
  StatefullContainer This one basically stores the state of the page when you leave it, and restores it when you navigate onto it. This doesn't have a stack of back or forward pages history, it keeps one list of states and applies it whenever you navigate onto the page. So simply your last state is restored once go navigate to the page. Think Good Memory.

There is a lot of detail in these controls that will require a separate post, but the point to take away is that you can easily create your own container - it's not too hard. And your custom container can exhibit whatever semantics or behaviours that suit your needs, for example you can extend these to store the state in isolated storage and instantiate it back on arrival so that the user can continue where he/she left. I assure it this is very extensible, which is why you see a lot of base classes and interfaces.

5. Application-level Integration: I describe nRoute as an application-flow framework and to fulfil those ideals I created a set of "Application" types that mirror the containers models I listed above. Think of these as application-level containers, that in effect link up with a container say on the root visual. So what does that mean, it means you set up a default container for navigation through out the application using hooks-up with the actual container. I suppose this is a bit hard to describe, until you see it in action, but below is a visual connection between the controls and the application they tie up with.

NavigationApplicationModelsOverview

I am not sure how much you can get out of these diagrams, but again the core idea is to register any container as an application-level container to which Urls can be navigated to by default - without having to specify who is going to be the handler. Please see the sample app for what this in effect means.

6. Browser Navigation Integration: This is already getting very long, but one important thing the "application-containers" also provide is Browser integration - which means deep-linking and deferring to the browser-shell for things like navigating back-forward and stuff. I have a very cool implementation, that uses the UnFocus History Keeper script but without any js files to reference etc in the HTML page as it just injects the javascript into the page. Critically, the javascript file itself is only 4KBs uncompressed, and is embedded into the assembly itself.  Like everything else you can extend this too, and for details you can look forward to a future post (so I'll skip another class diagram :).

There is so-much detail to elucidate with a framework like this, but I am perhaps poor in both explaining and documenting - still my hope is, this helps. Forthcoming will be a series of posts that will go over each aspect in detail. But as a highlight please do check out two things, one the sample application with full source code and second a post on how you can consume all this with a higher level API. Both these posts will give a richer idea of what's possible, than the plumbing thesis I just gave. Also, I would greatly appreciate any feedback on the API and usability aspect of the code, especially since this is my first open-source project.

Code at http://nRoute.codeplex.com - as of now specifically for SL2 no WPF version yet, but should work with SL3.

In a lot of things that MVC brought (besides reminding me how much I hate classic asp) what I loved the most was the routing engine. The routing feature was beautiful because it provided for loose-coupling, whilst being structured and rich enough to be actionable. Given that, and for structural and development modularity purposes I adopted the .NET 3.5sp1 routing engine for an URL based-navigation framework for Silverlight.

Basically it works pretty much like MVC/asp.net routing, you set up the routes to yields UI Objects. In this case we pass in a relative url (like "Customer/EditOrder/39/") along with an optional name-value collection (a dictionary basically) as request parameters. You can think of the request parameters as QueryString's collection or Form's input-value collection. What you get out from the routing engine is a "NavigationResponse" type, that contains a UI Page (basically a FrameworkElement) and another name-value collection. The name-value collection in the response is a merged collection of the request name-values, plus what it parsed from the URL and any defaults name-values you had set up with the route.

The other thing I've tried is to marry navigation with the routing, particularly because Silverlight controls aren't inherently statefull as pertinent to navigation - think html pages, like when browsing a web-form and you click back, the page is rendered in a state you left it in, with some exceptions to the rule.  How we achieve this "statefulness" is with the following interfaces.

PageState

Mostly we just use the IPageNavigator interface that brings together the two base interfaces, along with a title property. Hopefully it should be self-descriptive, but IPageInitializer interface is called to initialize a page pre-displaying it. The InitializePage method takes in a name-value collection, which as you can guess comes from the routing engine's response. The IPageState interface is used to extract and inject state into a page, so when we browse forward or back the UI get's a name-value collection to help it restore it's state. It's kind of like the viewstate in concept, but you have to put the relevant state in and out yourself as the controls themselves don't collude in state management. Also one of the thing we want with M-V-VM pattern, is to manage the state in the ViewModel - these interface helps with that by separating the state management. Additionally, the routing engine is geared to take this into consideration, so in the code to plug in routes we register a route handler with the following constructor.

public NavigationRouteHandler(
	Func<ParametersDictionary, FrameworkElement> pageResolver,
	Func<FrameworkElement, IPageNavigator> navigatorResolver) 
{ 
	... 
}

Basically, it takes in two handlers, one to get a FrameworkElement for displaying in the UI and the other to get the page navigator (IPageNavigator) out for helping with the navigation.  This separation of the FrameworkElement and IPageNavigation is in recognition of the ViewModel, but it doesn't force you - so, if you don't need a IPageNavigator or don't implement the interface just pass in null. Or if your page itself implements the IPageNavigator, then return the page. All the three scenarios are shown below, which also shows how to register routes, defaults and constrains:

void SetupRoutes()
{
	// we can pass in default values in routes
    var _defaults = new ParametersDictionary();
    _defaults.Add("OrderId", -1);

	// we can also pass in constraints 
    var _constraints = new ParametersDictionary();
    _constraints.Add("OrderId", "\\w{2}");

	// here we register a route with no IPageNavigator
    RouteTable.Routes.Add("Sample1", 
		new Route("Customer/NewOrder", null,
        new NavigationRouteHandler(p => new DummyControl1(), null)));

	// here we register a route, with the page itself implementing 
	// the IPageNavigator and it also has default values passed in
    RouteTable.Routes.Add("Sample2", 
		new Route("Customer/EditOrder/{OrderId}/", _defaults,
        new NavigationRouteHandler(
			p => new DummyControl2(), u => (IPageNavigator)u)));

	// here we register a route with the page's ViewModel implementing the 
	// IPageNavigator via the DataContext and we also have constraints set
    RouteTable.Routes.Add("Sample3", 
		new Route("Customer/DeleteOrder/{OrderId}/", null, _constraints,
        new NavigationRouteHandler(
			p => new DummyControl3(), u => (IPageNavigator)(u.DataContext))));

}

This is very similar to asp.net or MVC routing, the difference being we have a custom route handler for Silverlight / WPF that implements the IRouteHandler. And if you don't like it or your setup is hooked up differently, just create your own IRouteHandler implementation and you are good to go. Essentially it has the same extensibility semantics that MVC has, and the workflow is geared towards a request-response type of setup. I hope you did notice the {OrderId} parameters in the route URL, they are parsed and included in the response's name-value collection. One omission for Silverlight is that we can't pass in anonymous types to set up constraints or default values because we can't reflect on them outside the declaring assembly.

Like I said earlier I have tried to marry routing and navigation, and so we have something called navigation containers. The containers are simply interfaces that imply a navigation model, and I have two of them build-in - one is a simple navigation container which you pass in a URL and it just returns the UI but doesn't store any history or anything. Another one is called BrowsingContainer that stores history, caches the state, and can browse forward or back. Just like everything else you can create you own containers to implement say roles-based validation on URls or extend them for deep-linking within the browser.

NavigationContainers

A benefit with these interfaces is that you can expose them through a dependency injection container, and thus loosely couple the "pages" within the app. Another important point to remember is that you route against or rather navigate in a container even though the routes are registered statically/globally - this means we can have two or more navigation containers controls (think WPF BrowserControl) and each will work with all the routes registered. I also use these interfaces as ViewModels for navigation container controls, so you can easily create your own custom skins with all the glitter and jazz you want - I just sampled one with the Silverlight.FX transitions. It's quite easy.

There is a lot more to say, but for now lets keep it for the future - however I am working on integrating this with Prism 2 and creating an asp.net like site map control. In the sample below do notice that the pages keep their state during back/forward navigation and their memory consumption is constrained to the loaded page (plus the saved states).  I'll put up the code later on CodePlex, it needs some scrubbing, Cheers.

Get Microsoft Silverlight

PS: I wanted to mention and thank this excellent series on MVC routing.

DTD -> XSD -> .NET Types

Posted by Rishi on 08-Feb-09 1:47 AM - Comments (0)

Tags: , , | Categories: .NET, Tools

DTD (or Document Type Definition) is one of the original schema languages to come out with the XML 1.0 standards. However, in the .NET world it is rather unpopular, owing perhaps to it's complexity, unxml-like format and Microsoft's embrace of XSD. All the same, if you happen to run into a DTD schema document, which I did, there is a great online convertor available at http://www.hitsw.com/xml_utilites/ which can covert XSDs from DTD or XML Documents to DTD. It also supports generating XML schemas from XML Documents, just like Microsoft's Xsd.exe tool available with Visual Studio.

Also worth mentioning is the Xsd2Code Visual Studio plugin available at Codeplex. As the name suggests, it converts XML schema files to C# or VB.NET code, again like Microsoft's Xsd.exe tool. However, what is nice is it also adds explicit support for serialization and deserialization, nullable types, INotifyPropertyChanged and most importantly generic collections. Cool stuff.