Square Away: A Windows Phone 7 Game using nRoute

Posted by Rishi on 19-Jul-10 7:17 AM - Comments (9)

Continuing with my efforts to showcase how to create end-to-end applications using nRoute, this time we have a Windows Phone 7 (WP7) based board game called Square Away. It is actually one game out of a multi-game application I'm creating for WP7, and is based on the "Bubble Breaker" theme. To create the game we'll use the MVVM pattern, creating all the three triads and then use nRoute to bring together everything into one squarely game.

Squares

A word of caution, this is not a super optimized application and is clearly designed to showcase what nRoute has to offer rather than creating an end-user application.  More...

Creating a Netflix App using nRoute again: Now in WPF

Posted by Rishi on 12-Jul-10 5:48 AM - Comments (6)

Tags: , , , , | Categories: .NET, WPF, nRoute, Code

Couple of days ago I published a sample app in Silverlight that fronted Netflix's oData API - well, now I've ported the same app into WPF again making use of nRoute Framework. It like before demonstrates how you can build an end-to-end application using nRoute's navigation framework and MVVM related features-set on WPF. 
 nNetflix2
nNetflix1

As this is just a port, the preceding Silverlight based step-by-step guide is fully applicable here; besides templating and some implementation details the through-process is about equivalent - and so in this post I won't go through the nitty-gritty of designing the app, rather I'll just discuss the broader ideas, issues I faced, and changes I had to make to up-port it to WPF. More...

Creating a Netflix App using nRoute: A Step-by-Step Guide

Posted by Rishi on 30-Jun-10 3:04 AM - Comments (4)

With the latest release of nRoute we've added a trove of navigation-related features, to explain and demonstrate these features I've put together an end-to-end application that fronts the Netflix's oData Catalog. And so in this post we'll go through using these feature in a step-by-step manner to cumulatively compose a rich, extensible, and loosely-coupled application. Here is what we are going after:

PersonListing

MovieView View the nRoute's Netflix App (note you can also install the application on your desktop).

Guide Scope

Right off the bat, let me be clear, this post does not show you how to consume oData services or explain how to design iPad'ish UIs or troll on the virtues of MVVM - it purely concentrates on plugging-in nRoute's navigation and related features to compose our demo app. Familiarity with nRoute concepts is not a must, but will be much helpful. Secondly, just as I finalized this post, Netflix switched from a purely server-side paging-model to a hybrid client-server paging-model so I had to revisit the code, hence there might be a bit of mismatch from what's shown here and the actual code.

Step 1. Application Setup

For our application we'll split up the solution into two projects, one the main Silverlight (xap) application and the other a class library which will hold the Netflix service. And so first, in our data project we need to add a service reference to the Netfix oData Catalog.

CatalogService

We also need to need to add references to nRoute, so in both our Silverlight projects we add references to nRoute.Framework.dll, along with its dependencies System.Observable and System.Windows.Interactivity. And lastly you need to cross-reference the data project to the main application project. More...

nRoute Samples Revisited

Posted by Rishi on 19-May-10 2:58 PM - Comments (13)

Tags: , , , , , | Categories: .NET, nRoute, Silverlight, WP7, WPF, Code

Post the new of release of nRoute, I've updated and upgraded seven sample applications from earlier releases to the latest version.

1. Future Desktop 2 [Silverlight 4, nRoute.Framework]

Future Desktop 
Future Desktop was the first ever demo-app for nRoute in Silverlight 2, and since then we've come a long way - as a metric for progress consider in upgrading to the latest release of nRoute we've managed to cut the code count by half. Also, I could sense two non-quantifiable improvements, Panelsone nRoute is a lot less invasive as it generally stays out by the way of attributes. Secondly within Views, use of Blend based behaviors is a lot more productive than having to fiddle with xaml directly.

As can be seen on the right, I've added bit of the UI functionality - basically, now you can add, close, and refresh workspaces. However, I've removed the browser-shell integration functionality, which allowed you to navigate back or forward directly from the browser's shell - I did this because nRoute is now using Silverlight's built-in Browser History Manager which unfortunately can't tell when one navigates' back. Also there are some new keyboard shortcuts for managing workspaces.

Read more about the Future Desktop app
View the nRoute's Future Desktop 2 App here [Silverlight 4, nRoute.Framework]

More...

Let me expand on the title, with this post we will build an iPhone-styled Sudoku Game application in Silverlight using nRoute Toolkit. In terms of the architecture we will make use of MVVM design techniques in having separate Model, ViewModel, View plus related Services - and we'll piece them together in a loosely-coupled manner. As a starting point, we'll make use of a Sudoku puzzle-generating engine from an existing Siverlight implementation by Lee Saunders, upon this we will build our MVVM friendly layers.

SudokuPreview the Sudoku Application here

Application Model

In Lee Saunders' Sudoku implementation the puzzle-generating engine asks for an expertise level, and in return it hands over two arrays of string type that represented the incomplete and completed puzzle. However for a proper MVVM design that is not adequate, and so we have to encapsulate the puzzle in a proper model that enables both binding and serialization of the puzzle. Post churning, the resulting Application Model, shown below, has two principle concepts - a "Game" which is the puzzle board as such, and the "Box" which is an individual playable square of the board. Each Box type is uniquely indentified using a row and column placement on the Board, and per the Sudoku concept each Box can either be a given or must be user specified - so accordingly we have the IsPredefined property and a SuggestedValue property that holds the user's input. The ExpectedValue property holds the required/correct value, and the possible Suggested and Expected values are constrained using the BoxValue enumeration. The GameLevel enumeration holds the user specified expertise level.

Application Model

 ViewModel (VM)

Given we have the Model part of MVVM, we proceed to the VM - the main thrust of the VM is two fold, one expose the Game data for UI consumption, and two expose the Game-related functionality as UI consumable ICommands. And we do both, as shown below, with our GameViewModel class. Note we are using nRoute Toolkit specific implementations of ICommands.

GameViewModel

In terms of the implementation, the first thing we do is earmark the GameViewModel class as being ViewModel of the GameView UserControl - see the MapViewModel attribute. Also note, the ViewModeBase is an optional helper class that just implements INotifyPropertyChanged and exposes a method to use the same. Next, we expose the Game model via the Game property in the VM - this provides us access to the Boxes that make up the board in the UI. Following that, we have a series of ICommands like NewGame, Reset, Hint, Confirm etc that basically mirror the functionality in the model. And we also enable saving and restoring of a game in the IsolatedStore via the SaveGame and RestoreGame commands. We also have one Reverse Command (which are basically ICommands that execute in the View and are triggered from the VM), the ViewBoardReverseCommand, that basically allows the VM to instruct the View to show the board visuals when required (a sample case is when we restore a Game from the IsolatedStore, the VM asks the View to show the board visuals immediately).

I'll also point out that the distinction between ActionCommand and ActionableCommand - the later allows us to specify a pre-condition to the execution of the ICommand. So for example, the SaveGame command is declared as follows:

   1: SaveGameCommand = new ActionableCommand(
   2:     () => IsolatedStore.SaveDataObject(Game, FILE_NAME), 
   3:     () => Game != null)
   4: .RequeryOnPropertyChanged(this, () => Game);

Line 2 is the execution handler of the ICommand, which in this cases saves the current Game in the IsolatedStore, and in Line 3 we specify a pre-condition to the execution which says that the Game should not be null - this as shown below has repercussion in the UI. And in Line 4 we use an extension method for ICommands to declare that whenever the Game property (of our INotifyPropertyChanged implementing) VM (i.e. this) changes, then re-evaluate the executable state of the command.

SaveGameView

View

For our View we have basically divided the functionality into two screens named Home Screen and Game Screen, these screens are implemented as Visual States of the User Control. Peppered on the screen are various functional elements that trigger various commands we have defined in our VM - for example the "Confirm" element corresponds to ConfirmCommand in the VM, similarly the "Easy" element triggers the NewGameCommand with an "GameLevel.Easy" enumerated parameter. Note, to keep things light and to my preference, all button like elements in UI are actually Border controls rather than Button controls, however you could change that if you like.

Two Screens

Now to automagically inject the appropriate VM we drop the BridgeViewModel behavior onto the UserControl (see below) and optionally, if we wanted, through the same behavior we could also specify some control-lifetime related commands against the VM (eg. command to trigger when the User Control is loaded).

States And BridgeViewModel Behavior

In the Game Screen, the 9x9 board is an ItemsControl bound to the Game.Board property from the VM, and the ItemsControl's ItemsPanelTemplate is a custom Grid control with 9 columns and 9 rows. Further, the ItemsControl's ItemTemplate shows either a Grey'ish Border (i.e. pre-defined value) or an interactive Blue'ish Border (i.e. user-defined value) control. We position each item in the grid using a custom "SetParentGridPos" behavior which binds the grid position to the Col and Row property of the Box Type from our Model. And to enable user specifying the Box value, we rig the Blue'ish Border control to trigger SetBoxValue command in our VM. However to enable the use of the command within the DataTemplate, we need to relay it from our VM - so we first we declare a static RelayCommand, and then bridge the relay from our VM, that is done using the BridgeCommandBehavior (again see the screenshot above).

ViewServices

You can think of ViewServices in nRoute as services that are implemented visually - and here we have two such ViewServices, one that shows messages and another one that get a user's input.

ViewServices

Above are the visual interpretations, but the VM actually uses something like this:

ViewServicesInterfaces

In our app, both these interfaces are implemented in the code-behind by the GameView type UserControl. Now there are many other ways to do this, but I am comfortable with what is essentially a visual implementation to be implemented within the View's code-behind. Also, because the VM doesn't take any hard-coded dependency on the View, you can change the visual implementation at any point as long as the defining contract remains the same.

   1: [MapViewService(typeof(IBoxValueViewService), 
   2:     Lifetime = ViewServiceLifetime.DiscoveredInstance)]
   3: [MapViewService(typeof(IMessageViewService), 
   4:     Lifetime = ViewServiceLifetime.DiscoveredInstance)]
   5: public partial class GameView 
   6:     : UserControl, IBoxValueViewService, IMessageViewService
   7: {
   8:     //  IBoxValueViewService and IMessageViewService implementations..
   9: }

Above we use the MapViewService attribute to earmark the GameView type as the concrete implementation of both ViewServices, also note we are setting the ViewService's Lifetime to be "DiscoveredInstance", which means nRoute will look for the implementation in the VisualTree at runtime. And in terms of using the ViewServices in the VM, we use the ViewServiceLocator static class as such:

   1: var _messageViewService = ViewServiceLocator.GetViewService<IMessageViewService>();
   2: _messageViewService.ShowMessage(message);

Bootstrapping

One last point, to use nRoute you need to bootstrap it by adding it to the application's ApplicationLifetimeObjects collection, so in App.xaml we need to something like this:

   1: <Application  ...
   2:     xmlns:nRoute="clr-namespace:nRoute.ApplicationServices;assembly=nRoute.Toolkit">
   3:     <Application.ApplicationLifetimeObjects>
   4:         <nRoute:nRouteApplicationService />    <!-- BOOTSTRAP nRoute -->
   5:     </Application.ApplicationLifetimeObjects>
   6: </Application>

Summary

So here what we've got is an end-to-end example of using nRoute to develop a MVVM type application, right from the ApplicationModel to the ViewServices. Further, by cleanly delineating the various application parts and using nRoute to bring them together we usefully get a loosely-coupled but cohesive application.

You can view the Sudoku Application here,
and download the source code from Codeplex

Update (24-1-2010):

I updated the application to show a waiting indicator (by Chris Anderson) when creating the puzzle, as it was taking an inordinate amount of time. I also moved the new game generation code into a separate service (see IGenerateGameService), which makes use of a background worker thread so the UI should be a bit more responsive.

Introducing Cloud Light: a 10KB Application Runtime in Silverlight

Posted by Rishi on 13-Jan-10 7:38 PM - Comments (15)

Tags: , | Categories: .NET, Code, Silverlight, Technology

For the Mix10K smart coding challenge, I've create an application runtime that hosts, manages and runs cloud-based applications. The runtime is called Cloud Light, and per the rules of the Mix10K challenge the code and visuals weighs-in less than 10KB. The runtime environment also features an online application store from which you can download and install applications.

Cloud Light ScreenshotView the Cloud Light in the Mix 10K gallery and please vote for it.

Runtime Overview

  • Provides basic window management capabilities like opening, closing, activating, minimizing and restoring of windows
  • Allows you to install applications directly from the web
  • Installed applications information is persistent, with the applications themselves downloaded when the runtime starts
  • Allows you to uninstall applications with a single click
  • You can also install Cloud Light as a Silverlight Out-of-Browser Application (right click and choose "Install Cloud Light.." from the context menu)

Title Bar Overview

The Title Bar shows the active application's title and also show the current date-time. Additionally, it features four buttons on the top-right corner that enable full-screen toggling, showing/hiding of the application store, minimizing of the active application and closing of the active application.TopBar

Applications Store Overview

The online Application Store lists all currently available application in the Cloud. To install any application just click on the entry title, and the application is downloaded and installed - once installed, it should appear in the Application Bar. Going further, more applications will be available through the store.

InstallableApplications

Application Bar Overview

The Application Bar hosts all the currently installed applications, each application getting an icon for itself. The icon also with a highlight represents a running application, and each application can only have one instance running at a go. A single click to an application icon starts the application, if already running it activates it, if previously activated it minimizes it, and if minimized it maximizes and activates it - really simple, right. Also if an application is open, Shift+Clicking the icon closes it and by Ctrl+Shift+Clicking on the icon you can uninstall the application.

AppBar

Extensibility

Apart from the limited applications selection available in the Application Store, you can also create your own applications and install them using the Console application. In a separate post I will detail how you can create your own custom applications and install them.

InstallAppCommandLine

Another simple point of customization is setting the wallpapers, again through the console - so something like "setwallpaper -url:http://adsoftheworld.net/download/windows7/winwall7057_23large.jpg" will change the background into:

CloudLight3

And in addition to the built-in Commands, you can also create custom Console-based Script Commands, and have them automatically register with and be availed through the Console Application (see Silverlight Console).

Summary

So for 10KB worth of c# code and xaml, I think we have a surprising functional runtime that is both extensible and light thanks to Silverlight. It in some-ways can be seen as a prototype for a managed Cloud OS that relies on the Cloud but provides applications in the form we know them today. And in terms of the design it speaks to the simplicity and discoverability that iPhone brought, something that I think needs to be embraced in desktop-applications' designs.

View the Cloud Light in the Mix 10K gallery here
and please vote for it if you like it.

Acknowledgements
Default Grass Wallpaper by Radoslaw Rokita [vathanx@live.com]
Application Icons by Judge

One of the problems with MVVM designs is the inability of the ViewModel to singularly effect change(s) within the View; yes, you can use data-changes through data-binding as a crude-bludgeon, but I'd rather have the right tools for the right job. And that is where Reverse ICommands come in, they allow you to execute an ICommand in your ViewModel and have it trigger a set of specified action(s) in the View - the reverse taxonomy speaks to the fact that reverse ICommands targets your View rather than the ViewModel.

AvatarView the sample application here and the source code is also available at Codeplex.

Design: Extends ICommand

In working terms reverse commands are ICommands that acknowledge when they execute - the acknowledgement gives us the ability to respond to them from within the View. Implementation wise, see the IReverseCommand interface, we only add a CommandExecuted event to the ICommand definition.

IReverseCommand

The other part to reverse commands is the ReverseCommandTrigger behavior, to which we can bind our reverse command and associate one or more Trigger Actions to invoke when the associated command is executed. For example, in the Silverlight Console Project the Console definition has a "Beep" method to which we have to make a beeping sound (obviously) - however, the beeping sound playing control lies in our View and we have to trigger it from our ViewModel. So using reverse commands, first in our ViewModel we declare the reverse command property, initialize it to do nothing in our ViewModel (though you can have it do something else), and execute it when asked to beep (the OnBeep method), have a look:

   1: // we define our reverse command as a property in our ViewModel
   2: public IReverseCommand BeepReverseCommand { get; private set; }
   3:  
   4: // and we set it up like this in our ViewModel
   5: BeepReverseCommand = new ActionCommand(() => { });
   6:  
   7: // we handle Beep call request in our ViewModel and Execute the reverse command
   8: protected override void OnBeep() {
   9:     BeepReverseCommand.Execute();
  10: }

Then in our View, the XAML features the Media Element control and a reverse command Trigger which plays the media:

   1: <!-- We define the sound playing Media Element -->
   2: <MediaElement x:Name="beepAudioMedia"
   3:     Source="/Resources/beep.wma" Volume="1" AutoPlay="False"/>
   4:  
   5: <!-- And we set up Reverse Command Trigger to play the media -->
   6: <nTriggers:ReverseCommandTrigger ReverseCommandBinding="{Binding BeepReverseCommand}">
   7:     <Behaviors:PlayMediaElementAction TargetName="beepAudioMedia"/>
   8: </nTriggers:ReverseCommandTrigger>

As you can see, the workflow of reverse commands is very similar to regular ICommands, except we reverse the receiver/sender roles - the ViewModel here explicitly triggers the Command by calling execute, and the View hooks up Actions to go with the execution of the Command. Also note, all the ICommand implementations in nRoute are reversible because they all implement IReverseCommand - so you can use them as regular and/or reversed commands.

Usage: An Example

The attached sample application is really very simple, it basically has three screens and we control the flow and interaction between them from our ViewModel using ICommands and IReverseCommands. The three screens are realized as Visual States on the View and, as shown below, the Home Screen helps get a user's response to a question, the Trailer Screen shows a movie trailer and the Message Screen self-descriptively shows a message.

 SampleAppViewViewModel

Within our ViewModel, the Home command navigates to the Home Screen, the PlayPause command toggles the pause-state of the trailer, the Response command gets the user's response from the Home Screen. The reverse commands help navigate between the screens by changing the Visual State of the View, and the play/pause reverse commands do as they suggest. The idea here is to show how from within the ViewModel we can, without direct dependencies, control the View - like when we navigate away from the Trailer Screen we pause the movie and when we enter into the Trailer Screen we resume the movie all from the ViewModel. Even the playing state of the trailer is kept within the ViewModel, similarly when we get the initial question's response the ViewModel decides which screen to navigate to, and if appropriate which message to show. All this builds on the separation of concerns principle, and though the functionality here is petty, the application of ICommands and IReverseCommands helps us manage the View-ViewModel interaction in both directions.

Summary: ICommands Reversed

ReverseCommandsModel

Per the principles of MVVM, in SL, we have two primary ways of communication between the View and the ViewModel - one, data-changes signifiers that rely on data-binding, and two, ICommands based invocation of actions from the View. Data-changes as a mechanism for inter-communication works for some cases, but in other cases it is too implicit and imprecise, and this is where ICommands weigh in - they are good for explicit, loosely-coupled, and strongly-typed invoking of actions. However ICommands are one-way creatures designed to be invoked from the View, and handled within the ViewModel.

On the other end, invoking of actions from the ViewModel-to-View is the functional gap that IReverseCommands fulfill, and just like ICommands they are explicit, precise and strongly-typed. Further, as with ICommands you also get ICommands-associated functionality like can-execute checks, enabling-disabling of ICommands, and explicitly defining of dependencies like in nRoute. Now, technically there might be many ways to achieve what reverse commands do but for me the fact that here we have a loosely-coupled setup which makes use of the binding infrastructure in SL and extends one the primary communication mechanism to work in reverse is a handsomely meriting solution.

You can view the Sample App here,
you can download the Sample App source-code here,
and read about the rich support for ICommands in nRoute here.

Following up on Part I which described the workings of the Resource Locator Framework (RLF), in this post we will create a search application that uses the RLF to collate search results from various RSS-feed providers. The RFL will be used to earmark and resolve (at runtime) all the various providers, and results from which will be displayed in a tabular format using a MVVM type solution. Additionally, we'll make use of Rx-framework like Observables to asynchronously gather and compose search results.

ResourceLocatorSampleSmall  View the sample application here and the source code is also available at Codeplex.

Getting The Search Providers Results

In our sample application the provides are essentially search-engines that output results in RSS-feed format, and within our application they are represented by an ISearchProvider interface (shown below). The search results are materialized into the SearchResult type, which corresponds to an RSS-feed item and has Title, Description, Dated and Url fields. Further, for searching a provider takes the search keywords, and returns an IObservable - using which we can have the results asynchronously pushed to us.

SearchProviders

The IObservable/IObserver pairing is also very simple, just to recap for those unfamiliar - you can think of the Observable as the publisher and Observer as the consumer. When the consumer wants to consume, it subscribes to the publisher and the publisher can do three specific things - push a series of values (of an agreed type i.e. type T, via the OnNext method), indicate that it is done (via the OnCompleted method) or if an error were to occur relay that (using the OnError method, which also stops the process). Further, when we subscribe we get an invoke-able token (IDisposable type) which the consumer can (prior to completion) use to opt-out/unsubscribe from the publisher's output.

ObservingProcess 
Now in our case, the ISearchProvider is the publisher, which when asked (using search keywords) publishes a series of search results to which we subscribe. And in our sample we have realized the publishing-consuming using nRoute's build-in IObservable<T> and IObserver<T> implementations called RelayObservable<T> and RelayObserver<T> classes. Below is the outline of ISearchProvider's Search method's implementation which pushes the WebClient's response to the RelayObserver<T>'s  subscribers.

   1: var _observable = new RelayObservable<SearchResult>();
   2: ...
   3: _webClient.DownloadStringCompleted += (s, e) => 
   4: { 
   5:     if (e.Error != null)                      // incase of an error
   6:         _observable.OnError(e.Error);
   7:     else if (e.Cancelled)                     // if cancelled we indicate completed
   8:        _observable.OnCompleted();            
   9:     else {                                    // else, we parse and push the results
  10:         ParseAndPushResults(e.Results, _observable.OnNext); 
  11:         _observable.OnCompleted();            // we also indicate we are done
  12:     }
  13: }
  14: ...
  15: return _observable;                           // return the observable
 
On the other end of the stick, when we want to consume the output of the publisher above we have to subscribe - and for that we can either use a RelayObserver<T> or equally use the Subscribe extension method on any IObservable<T>. So below we are subscribing to the ISearchProvider's Observable and thereon we handle the three possible return cases. Also note the cancellation token (IDisposable) variable which we keep around incase we want to cancel. 
 
   1: var _cancellationToken = _searchProvider.Search(SearchText).Subscribe<SearchResult>(
   2:             (r) => _results.Add(r),                 // on result
   3:             (e) => ShowError(e),                    // on error
   4:             () => _isLoading = false);              // on completed
 
And that's it - we have a bona fide asynchronous communication archetype to handle search results in our ViewModel. The rest of the job just involves monkey code to marshal the results to the UI. Also note, because Silverlight can't directly access web-based RSS-feeds (unless the sources opt-in), we have got local ASP.NET proxies to go with the providers.

Getting The Search Providers Themselves

Given we know how to get the search results, our next step is get the providers themselves - and for that we'll create a specific mapping which locates ISearchProvider resources/providers. With the RLF, my general practice to create explicit mappings in a three step process - first create a meta-data class (if needed), create the IResourceLocator, and third create the mapping attributes. We'll cover these steps point-by-point:

Step 1. Create the Metadata Class 

The metadata is many-times optional but in this case we want to get a Title for the search provider and an Icon (path) to go with that. Plus, for ease of use we also store the name of the provider and the implementation type in the meta-class itself.

   1: public class SearchProviderMeta
   2: {
   3:     public SearchProviderMeta(Type providerType, string name, 
   4:         string title, string iconPath) { ... }
   5:  
   6:     public Type ProviderType { get; private set; }
   7:  
   8:     public string Name { get; private set; }
   9:  
  10:     public string Title { get; private set; }
  11:  
  12:     public string IconPath { get; private set; }
  13: }

I think that was painlessly-simple, but the idea is you should be able to use the meta in a strongly-typed fashion.

Step 2. Create the Resource Locator

As you know a resource locator is just an implementation of IResourceLocator interface, and here we have a very straightforward implementation for the search providers.

SearchProviderLocator

Our search provider's IResourceLocator implementation (DefaultSearchProviderLocator class) shown above is quite simple, it returns an instance of the meta-class we created earlier, it also provides the name of the resource, and by initializing the provider-type it can return instances of the provider. Here actually the implementation of IResourceLocator is numbingly-simple but in other cases the Resource Locator can do all kinds of fuzzy things - it's an abstraction that allows each type of resource or even each individual resource to have its own realization strategy. To give you an example of the fuzziness, the default View Services locator in nRoute can look into the Visual Tree and provide you an instance from there or if applicable a resource can opt to register/unregister an instance of itself as it sees fit (see this post for more info).

Step 3. Create the Resource Mapping

The third and final step is to create an attribute that earmarks the resource as being a search provider, for this we have to derive from the MapResourceBase attribute.

MapSearchProviderAttribute

Above our MapSearchProvider attribute in its constructor takes in the name, title and icon path information, using which it creates the meta-class from Step 1. Next, from the base class we override the GetResourceType method which tells the RLF as to which type of resource we are mapping - the answer of course is ISearchProvider type here. Note, the targetType parameter tells us onto which type this attribute is applied on - which in this case has to be our provider type and we duly check for that. We also override the GetResourceLocator to which we return our DefaultSearchProviderLocator from Step 2 - and this then resides in the Resource catalog for ISearchProvider type. I think it is fairly simple, despite the explicit steps involved - however. if you wanted something more ready-to-eat in that case you can use the MapResource attribute or MapService attribute and forge custom mapping.

Earmarking and Consuming The Providers

We've now got the requisite resource mapping and locating functionality in place, and we can just tack the MapSearchProvider attribute and be off to business, so for example:

   1: [MapSearchProvider("BingProvider", "Bing Search", 
   2:         "/nRoute.Samples.SearchProviders;Component/BingLogo.jpg")]
   3: public class BingProvider : ISearchProvider 
   4: {
   5:     ...
   6: }

Now to individually retrieve the BingProvider instance or its locator you can use the following code, note "BingProvider" is the resource identifier name:

   1: // Gets the resource
   2: ResourceLocator.GetResource<ISearchProvider>("BingProvider");
   3: // Gets the resource locator
   4: ResourceLocator.GetResourceLocator<ISearchProvider>("BingProvider");

However, for use in our ViewModel we are interested in getting all the ISearchProvider types registered - not just one. For that we can access the resource catalog (note, the RLF creates individual catalogs per resource type), and we can also listen to any changes as the catalog implements INotifyCollectionChanged. The Resource<T> is a singleton class that holds the catalog, and the ResourceLocator static class helps with resolving, checking for individual resources or their representative locators.

ResourceCataloging

Using the two classes above we get hold of all the locators, and then rig up columns per-provider to show the results - we make use of the metadata held by the locator to display the icon and title of each provider. The locator also acts like a factory for ISearchProvider instances (per search), which we use to get the search results.

Dynamically Getting More Search Providers

The point of mapping using the RLF is that all the resources are discovered and cataloged at runtime, however the fun doesn't have to stop there. RLF also supports dynamically downloading and mapping all earmarked resources within a DLL or XAP file. To demonstrate that with our sample app, we have a two providers housed in an external DLL which on-demand downloaded and mapped - and because the ViewModel is listening changes to the catalog it is immediately reflected in the UI (try the "+ Provider" button). So to download and automatically map resources we use the RemoteResourceLocator class, have a look:

   1: var _remoteResourceUri = new Uri("nRoute.Samples.SearchProvidersEx.dll", UriKind.Relative);
   2: var _resourceLoader = new RemoteResourceLoader();
   3: _resourceLoader.LoadResource(_remoteResourceUri);
 
Alternatively, you can download assemblies/xap-packages yourself and map each assembly (which is the unit of mapping, as it were) using the AssemblyMapper static class. Note, when we map we not only map the Search Providers but all kinds of earmarked resources like Services, Modules, ViewModels, ViewServices etc.

Summary

The point of this sample application was to show how you can at runtime discover and resolve resources using the RLF. Further, by creating custom resource mapping/locators, we were able to precisely materialize resources along with the metadata associated with each individual resource. The process of creating custom mappings involved creating a meta-class, followed by a resource locator (which owns the materialization strategy), and lastly a mapping attribute which brings together the two. We also have the ability to dynamically load remote resources using the build-in loaders, and any earmarked resources therein are automatically registered.

You can view the Sample App here.
and you can download the Sample App source-code here.

Note, for the sample project be sure to build the nRoute.Samples.SearchProvidersEx before running the project (it sends the DLL to the Web Project) and set the Web Project as your startup project.

Value Converter and Command Relays for Visuals-Related Logic

Posted by Rishi on 25-Aug-09 9:06 AM - Comments (5)

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

A lot of the work I've been doing lately with .NET eventing and stuff comes down to the concept of resource-management - like how do we manage our resources' lifecycles without causing unintended negatives (like memory-leaks or performance issues). On the face of it resource-management is a problem of pluses and minuses, creating and releasing resources per their need - but the fact is, with frameworks like .NET there is so much resources creation and disposing going-on that we figuratively end up managing needles above a haystack.

The Idea: Take'em down with me

More to the point, I have this idea of managing the disposing of resources by creating a persuado supporter-dependent hierarchy of resources - sounds fancy but it is really simple. And the other part of the equation is having an API that isn't too intrusive - this is quite important to me, as I think with tiresome APIs the usefulness whether-away like a new-year's resolution.

In practical terms the disposing of resources is based around this single interface, called IDisposeRelated - which has the following make-up:

   1: public interface IDisposeRelated
   2: {
   3:     event EventHandler DisposeRelated;
   4: }

Basically, you introduce this interface on any object that wants to limit the lifespan of one or more dependent resources to no more than its own - so good candidates include user controls object or event handlers. For example we could, append the IDisposeRelated interface as such:

   1: public partial class Window1 : UserControl, IDisposeRelated   
   2: {   
   3:     public event EventHandler DisposeRelated;    // IDisposeRelated Members
   4:  
   5:     public Window1()   
   6:     {   
   7:         InitializeComponent();
   8:         this.Closing += (s, e) => 
   9:            {if (this.DisposeRelated != null) DisposeRelated(this, EventArgs.Empty);};
  10:     }
  11: }

 

 

All we are saying here is that when closing the user control raise the DisposeRelated event, indicating that you want dependent resources to be brought-down too. Do note, I don't use the word "dispose" in the strict sense as with the IDisposable interface, which relates it to releasing unmanaged resources.

Dependent Resources: Proactively com'n down

Once we have the IDisposeRelated resource defined, we indicate the dependency using (mainly) extension methods - consider two examples:

   1: this.Writer = new StreamWriter(_filePath).DisposeWith(this);
   2: // or
   3: ParentWindow.LostFocus += 
   4:     new RoutedEventHandler(ParentWindow_LostFocus).DisposeWith(this);

In line1 we are creating a new stream writer, to which we append the "DisposeWith" extension method to indicate that it should be disposed off when disposing "this". And "this" would/could be any object supporting the IDisposeRelated interface - so in other words, because the IDisposeRelated interface indicates as to when it wants to dispose related resources, we listen to that and take down any earmarked resources with it. And that's it.

The Take Down

Now, when I say "take-down" resources - the garbage collector would stare blankly first, but basically we know how to do certain stuff like with IDisposable objects we will call the Dispose method or with event handlers we can unregister it. For other stuff or when you want more control you can use another DisposeWith extension method definition that takes an action delegate (with the target passed in) to effect the "take-down" as you specify. For example:

   1: var _cache = new MemoryCache().DisposeWith(this, (c) => c.Clear());

In the case of the cache object above, the "take-down" concept in its context would mean clearing whatever is in the memory. The point being, if we can proactively add this instruction of how to redeem resources whilst creation (though you could still add these instructions later) we won't loose the proverbial needle in the haystack. Further, by earmarking resources by the "dispose with" instruction, we create this persuado supporter-dependent hierarchy.

Technically Speaking

Having specified "dispose with" for an object does not preclude you from disposing it earlier - just later if it hasn't been disposed then it will do it for you. Secondly, the "dispose with" instruction only holds a weak reference to its target, and so it doesn't itself become a memory leak source. Also, you could possibly have more than "dispose with" instructions against a resource and it will be fulfilled in a first-come first-serve basis. Further, the dispose with thing doesn't have to be based on a resource's parent's lifecycle, it could be based on a peer object or on some other domain context - which is why I said a persuado supporter-dependent relationship and not a parent-child one.

Performance-wise, I've not checked because I am still mulling over the validity of the idea. But, I don't think it would be too great of hit, because my current implementation is basically adding a weak handler against the "DisposeRelated" event. All the same, there are other ways to implement the same functionality, so we'll see about the performance.

This current implementation is very basic, possibly in the future, if it is worthy, we could add fancy features like LINQ based dependency evaluation or lazily attach it with a control's lifecycle. For now, it is something simple I am trying in my code, but like in a lot of cases ideas as these comes down to the usefulness v/s inconvenience of the feature.