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...

Posted by Rishi on 18-Jul-10 1:17 PM, 18 Comments

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...

Posted by Rishi on 30-Jun-10 1:21 AM, 42 Comments

ViewServices in nRoute are basically UI implemented functionality exposed as services for non-visual consumption - think a Status-Bar as IStatusInfo service. The underlying idea is separation of concerns, so that non-visual components like ViewModels don't have to take dependency on View-based controls or on platform specific contraptions. Now, there is nothing radical about this concept, but with nRoute we get first-class API support to specifically identify, implement and consume "ViewServices" and that's what is discussed in this post.

To demonstrate ViewServices I've put up a small demo called Web Xcel - it replicates the Office Web look and feel for a spreadsheet type application. However, it is no spreadsheet; I've just used the feel of a potentially real application to show how we can integrate and consume ViewServices in an application's flow as it were. Below are some screenshots:

Web Xcel

Web Xcel

You can view the Web Xcel demo app here.

ViewServices - The Basics

Before we get to some examples of ViewServices let me just briefly recap how to define and consume ViewServices - for a proper introduction see the introductory post to nRoute.Toolkit. Firstly, the functionality that a ViewService exposes is encapsulated in a contact i.e. an interface. The defined interface, is then implemented onto a control/object which we earmark with a MapViewService attribute along with some related options. So for example, in Web Xcel demo we have this IConfirmMessageViewService contract that allows us to confirm "something" from the user, the interface definition looks like:

   1: public interface IConfirmMessageViewService
   2: {
   3:     string Title { get; set; }
   4:     string Message { get; set; }
   5:     IDisposable Confirm(Action<bool?> confirmationCallback);
   6: }

This contract basically takes in a title, message and a callback that returns the response from the user - we'll get to the details ahead. However, this contract's implementing class is decorated with the MapViewService attribute as shown below:

   1: [MapViewService(typeof(IConfirmMessageViewService), 
   2:     Lifetime=ViewServiceLifetime.PerInstance)]
   3: public class ConfirmationViewService
   4:     : IConfirmMessageViewService
   5: {
   6:     // implementation 
   7: }

Now, the only notable thing with MapViewService attribute is the Lifetime option which tells nRoute how/when to instantiate/serve a request of the IConfirmMessageViewService - and in this case, it is going to instantiate a new instance per request. You have other lifetime management options namely singleton, weak singleton, discovered instance and self-registered instance. Singleton obviously means a single instance for all requests and the weak singleton option serves a single instance around as long one or more consumers are using it, once it is out of use it's GC'ed. The discovered instance in interesting, as it goes through the VisualTree to find the first implementing instance and returns what it finds. And the self-registered ViewService relies on an implementing control to register an instance of itself when available and unregister when going dark. The important thing to remember with these non per-instance options is the effect on state-management of having potentially multiple concurrent consumers as opposed to each consumer having their own instance.

To resolve a ViewService, we can make use of the ViewServiceLocator helper class that like any IoC component returns an instance. Also in cases where we have more that one implementation of a ViewService we can name each implementation and resolve the same by identifying its name. Now, to use the IConfirmMessageViewService we do something like:

   1: // set up the service
   2: var _showMessageVS = ViewServiceLocator.GetViewService<IConfirmMessageViewService>();
   3: _showMessageVS.Title = MODIFIED_WORKSHEET;
   4: _showMessageVS.Message = CONFIRM_WORKSHEET;
   5:  
   6: // we get the user's response
   7: return _showMessageVS.Confirm(confirmationCallback);

The idea behind the use above is to confirm from the User as to if we save the active worksheet, which has pending changes, before we open or create another worksheet. The visual implementation uses a dialog, as shown below, which confirms for the ViewModel how to proceed. 

Confirmation Child Window

The larger point to ViewServices is that your ViewModel is not concerned about how the visually-implemented functionality is rendered or responded to. It disconnects the implementation from its consumption, so for example you could change or put up a totally new visual implementation, and your ViewModel will be none-the-wiser but more importantly it won't have to be changed.

Web Xcel Demo's ViewServices

I'm not going to go through the full details of the ViewServices in the demo app (you have the code for that), but I'll just describe them and highlight some of the more interesting parts.

IOpenFileViewService

This ViewService is part of the toolkit itself, and as it self-suggests it opens a file dialog that returns a file stream. It is really simple, except the notable instruction is that that its use has to be instantiated directly by a user action such as a key press or a click event. Secondly, this is also very important, we can't open two back-to-back dialogs with a single user-interaction - so we can't save a file and follow it by a open file dialog, this manifests in an interesting solution in the demo app.

ISaveFileViewService

This ViewService does as it reads, and is also pre-packaged in the toolkit. One important distinction I'd like to make with this ViewService is that, it is not an "integrated-visual" in a sense that a Status-Bar is. It, like with other dialogs and ChildWindows, is extraordinary in the sense that it somehow appears from sky as opposed to being part of the VisualTree. This distinction makes a difference in how an instance of the specific ViewService is initialized, instantiated and returned - so a Status-Bar in the VisualTree may need to be registered/discovered whereas a Save File Dialog can be new'ed up.

IConfirmMessageViewService

I've already described this ViewService above, and as duly noted it makes use of a ChildWindow. The interesting part of this ViewService is that it takes in a delegate-based callback and returns an IDisposable. The IDisposable is like a token that be used to dispose the dialog - so in some cases when you want to say draw-down the dialog (from your ViewModel) before the user has addressed it, you can call the dispose method on the token. This pattern is also useful in cases when you want to show information-based dialogs like "Uploading" that users can cancel or when finished it can be disposed via your ViewModel. Again, note this an example of non-integrated visual - it falls from the sky.

IStatusViewService

This ViewService is used to update the current "status" of the application, basically visualized via the Status-Bar (so it's an example of an integrated ViewService). The defining interface to this ViewService is very simple, have a look:

   1: public interface IStatusViewService
   2: {
   3:     IDisposable UpdateStatus(string status);
   4: }

Again like the confirmation ViewService this ViewService returns an IDisposable token that can be used to call-off your status update. So for example, when done saving you can trigger the dispose on the token and the status-bar will revert to its default message. However, if another update has been received post yours, the dispose is auto-magically called for you by the status-bar itself - so in that case the token wouldn't do anything. In this way, it can support multiple updates to the status whilst having only one retractable-update active. As a side-note, you have to be careful about the given implementation in the Demo as it can lead to memory-leaks if you indefinitely hold onto the token - so always dispose them or change the implementation to a weakly-referenced one.

IDocumentInfoViewService 

The Web Xcel is like an example of a Single Document Interface (SDI), and to abet that this ViewService helps with updating the title and 'IsDirty' status of the working document. Obviously the implementation of this is very simple here, but the point made is how a ViewModel that that manages the active worksheet can visually reflect the status in the Shell. Secondly, this ViewService (like the IStatusViewService) is directly implemented in the code-behind of the MainPage.xaml (i.e. the Shell also the RootVisual). I am not sure if the MVVM cops would like this, but to me this a UI detail and it can be implemented in the View itself.

Balloon Notification ITimeoutNotificationViewService

This ViewService is implemented as a notification balloon, as shown in the screenshot. It has two main features, one that it supports a timeout of your notifications - so basically it shows the balloon for the given period of time and then closes it. Secondly, it also supports queuing of notifications - so whilst a single notification is being shown it queues the the others and plays them one-by-one in a first-register-first-shown manner. Now, this ViewService is implemented as a control, which I find to be a reasonable way to component'ize and expose ViewServices .

IInteractiveNotificaitonViewService

This ViewService like it suggests allows for a visual notification with an interactive capability in that if the user "interacts" with it, a callback notifying the same is raised. As far as the consumer (like a ViewModel) is concerned the "interaction" is an implementation detail - which in Demo's case happens to be a click on a header-type panel.

  Header Notification

So above, if the User happens to click on the yellow header bar - it would raise a callback saying the user interacted with the message and so do your thing. On the other hand, if the close button is pressed the callback would return saying that the user did not "interact" so do the other thing. Also, because this ViewService is practically a single-instanced (it self-registers itself) service that potentially serves multiple concurrent-consumers, the notifications are queued in a FIFO manner to ensure User's individual viewership for each and ever notification.

ViewServices - Not There Yet

So in this post and accompanying demo we've covered how ViewServices help us to abstract, expose, and consume visually-implemented functionality. This in my experience is an important and often ignored piece of the MVVM puzzle, which I hope by semantically capturing in a ViewService implementation provides for a better handle. However, there are lots of other aspects to this, especially in relation to View-Composition and that is something that needs more work. For example, how can we get contextual tabs integrated into the ribbon when a User is say editing a cell - obviously, you can do it (with something like Prism regions), but what is needed (or what I want) is to keep the View-composition logic out of the ViewModel/Modules and have a XAML-based way to dynamically integrate/compose bits and pieces of the UI together.

Also, some of the other things I want to provide is a generic modal-dialog strap-up that fuse nicely with ViewModels akin to what Nikhil Kothari showed in his post, but for a broader spectrum of uses such as Wizards. Now, some of the solutions would require the full nRoute which avails the routing engine and view-composition capabilities - obviously because the wheel has already been invented there. Other than that, currently we're not doing dependency injection which is big-problem and I want to address it quickly - there are some tricky problem to it making it play nice.

In many ways, a lot of these things are still fresh from the oven - so going forward I'd like to have more scenarios-covered with better formalization of the View-ViewModel interaction.

View the Web Xcel Demo here.
Download the demo app source-code and the nRoute.Toolkit from Codeplex
(note you require the accompanying nRoute.Toolkit dll)

Icons in the demo app are from the Silk Icon collection by Mark James (Thanks).

Posted by Rishi on 23-Oct-09 5:56 AM, 29 Comments

Categories: nRoute, Silverlight

With little Chinese naming ingenuity I present to you Office® 2010, the proper non-Chinese name being Officer 2010, in Silverlight 3. It is based on the the new opening screen in Microsoft Office 2010, and designed specifically to showcase nRoute Containers which I blogged about in my last post.

First, below are some of the reference screenshots from Microsoft Office 2010 apps.

Microsoft Word 2010 Screenshot

Microsoft OneNote 2010 Screenshot

And next are some screen captures of the demo app.

Officer 2010 Screenshot 1 

Officer 2010 Screenshot 2 

Officer 2010 Screenshot 3

To view the actual Silverlight sample, click here - it requires the Silverlight 3 runtime. As far as creating the application is concerned, I did it over two days using Visual Studio and Blend 3 Preview.

Do note this is not a functional application per se, and is not designed to mimic Microsoft Office Suite functionality - it is again, produced to demonstrate the concepts pertinent to nRoute. And since I've never used Office 2010, I can't speak to either the visual-accuracy or behaviour-similarity, plus the lack of fit and finish is quite obvious. Also, you will often run into the acknowledging request balloons, and by clicking the "Back" button up-top it will "showcase" an error - by design.

For a technical overview of this demo app, click here.
And to download the code,
click here.

Posted by Rishi on 19-May-09 12:34 PM, 22 Comments

Categories: nRoute

I've yet to cover all the features of nRoute in depth, but since a lot of people are downloading the framework and the demo app, I thought let me step through code in the demo app to at least provide a rounded overview of the features in nRoute. To structure the content, I will headline each significant part and highlight the relevant aspects in the code. Further, to make some distinctions clear, this post is divided into two parts, one relates to the Infrastructure in the demo app and the other relates to how the consumable/actionable content integrates with the infrastructure, using nRoute of course. Moreover, to get the most out of this long-long post please familiarize yourself with the basics of nRoute, using my series of earlier posts.


PART I: INFRASTRUCTURE SETUP

The Application Class

Right off the bat, in the app.xaml.cs we can see that the application class inherits from a custom type defined in nRoute called StatefullApplication. I've mentioned this before, but the idea of deriving off a custom application type is to primarily give home to a default container. The default container is an application-wide navigation container hook-up point, wherein any navigation without a specified container is handled - think unhandled exception handling as a mental model.

public partial class App 
	: nRoute.Navigation.Application.StatefullApplication { .. }
Now we have several types of navigation containers build into nRoute, and equally you can define you own custom ones. In this instance we are using a "Statefull Navigation Container" and its companion application class derivate (the StatefullApplication type) - I had earlier defined the Statefull Container as follows:

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 you navigate to the page, in either back/forward or direct navigation manner.

The StatefullApplication type provides a number of features, one that is pertinent here is the NavigationContainer property which allows us to set any navigation container as the application's default container - and as you will read ahead that is exactly what we do.

The Workspaces/Blades Model

Before we can dig deeper into the application class, I want to explain one of the core aspect of the UI - which is the blades/workspaces model that provides one or more tab-like containers for the application. Each workspace/blade is basically a StatefullContainer which can collapse or expand into full view, and features a title bar to its left (see Workspace.xaml). I've exposed all the interaction functionality of the workspace through an interface called IWorkspace, nothing special really - basically think of it as a specialized tab. Further, in order to show the blades/workspaces I created a custom panel called WorkspacesStackPanel - essentially it is like a horizontal accordion, specialized to only show one active workspace and vertical title-bars for all the other collapsed workspaces.

Workspace/Blades UI

To manage the workspaces there is the WorkspacesViewModel type, which should have really been called the WorkspacesController type. And like my suggestion, this is basically a simple application-wide controller for managing all the workspaces. Again nothing special, however for your own use you might want to amend this to allow adding/removing workspaces, with perhaps a more streamlined workspace-interaction pattern. This controller is exposed on the Application class using the read-only WorkspacesViewModel property.  

The Application Startup

The fun starts in the startup event of the application, we do a couple of things here:

  • We set the root visual to the MasterPage.xaml [Line 3]
  • We then create the workspaces, which initializes the mentioned WorkpsacesViewModel type [Line 5]. Note you can create your own strategy to customize the number of workspaces, in the demo app's case we try and read the "workspaces"  querystring key for values between 1 and 9 (try appending "?workspaces=7" to the Url, before the bookmark)
  • We set the DataContext of the root visual to the WorkpsacesViewModel, this cascading'ly hooks up the visuals [Line 6]
  • Next, we register for browser integration, this functionality is availed through the inherited base application class. Note, while registering we also specify the default Url, which in this case we read from the browser's current bookmark or use the specified default value ("Home/")  [Line 8]
  • Next, like before we set the active workspace's Initial Url by reading the browser's Bookmark or use the Default value ("Home/") [Line 9] - this allows for the deep-linking feature
  • And also we set up a handler that updates the Browser's Title when the active workspace changes [Line 11]
private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MasterPage();

    CreateWorkspaces(3); // delegates to a helper function
    ((FrameworkElement)this.RootVisual).DataContext = _viewModel;

    base.RegisterBrowserNavigationHooks(base.GetCurrentBookmarkOrDefaultUrl("Home/"));
    _viewModel.ActiveWorkspace.InitialUrl = BrowserIndexedNavigationBridge.RemoveBookmarkIndexerInfo(GetCurrentBookmarkOrDefaultUrl("Home/"));

    _viewModel.ActiveWorkspaceChanged += (s, e2) =>
        base.SetBrowserWindowTitle(this.NavigationContainer != null ? this.NavigationContainer.Title : null);
}

Browser Integration

One of the side-effect of the multiple blades/workspaces is that it complicates the browser-integration strategy, because the browser only keeps a single history-stack whereby we need multiple of these on a per workspace/blade basis. Not to worry though, because like everything else in nRoute the browser integration strategy is totally configurable. The solution in this case is that we append the bookmark with an indexer that identifies which workspace the bookmark belongs too (it looks like ¶3 or ¶1 postfix). The integration is achieved by overriding the CreateBrowserNavigationBridge method in the application class, and providing a custom implementation of type WorkspaceBrowserBridge. When the "bridge" adds to the browser history our custom implementation appends the bookmark with the active workspace index, and when the browser navigates back or forward it parses the workspace index and accordingly sets the active workspace and the Url. This allows us to have a single history-stack for multiple workspaces/bridges integrated within the browser, with full deep-linking support. As a notable, the browser integration behaviour is based on a simple interface of type IBrowserNavigationBridge.

Master Page

The master page (or shell if you prefer) is actually simpler than it appears, it is basically a three column by two row grid (as shown by the red lines), and three borders fill the grid area to define the rounded shape of the visual (as shown by the green borders). We also dynamically clip the grid as per the edges of the borders. The Icons on the left, are placed in a canvas and aligned to the bottom. The bar at the bottom is also a grid, and on the right we have stack panel that block-by-block fills in the side bar. 
 Master Page Visual Breakdown
The main content is an ItemsControl element which is data bound to the workspaces list, and uses the aforementioned WorkspacesStackPanel as the ItemsPanelTemplate.

<!-- WORKSPACEs -->
<ItemsControl ItemsSource="{Binding Workspaces}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <cnt:WorkspacesStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl> 
Visual Effects

Or the lack off, should be title as I absolutely took a minimalistic approach in recreating the reference UI. Since I made the app in SL2, I purposely deferred using visual goodies in favour of the goodness on offer in SL3 - particularly the GPU based shader effects and Perspective 3D. The one thing I did attempt was the hover-effect as without the visual-highlighting the navigation-links wouldn't be self-apparent. The hover-effect uses attached behaviours with an extensible model so that you can extend it to your custom controls, still it is quite comprehensive. The use template is also pretty simple, have a look:

<Border Style="{StaticResource SideButtonBorderColourBrush}" 
    hvr:Hover.HoverBackground="{StaticResource SideButtonHightlightBkgBrush}">
In the snippet above, we attach the behaviour to a border and say on hover (mouse over event) change the background to the brush identified. Depending on the visual element you can change the background, foreground and the border on hover. Note, you can adopt this behaviour for use elsewhere, but consider using storyboards to give transitions a visually engaging lift.


PART II: CONSUMABLE & ACTIONABLE CONTENT
 

Content Composition

To this point we have had the application's infrastructure basically all spelt out, without even having to delve into the actual content - which is good because we want minimal intermingling of the content and the infrastructure that surrounds it. In fact this is the forte of nRoute, that we can keep the content and containers loosely coupled from each other using only Urls - and nRoute takes care of the composition for you. Read about the basics of navigation-based  composition in my previous post.

Content Mapping

Now, for the composition to occur we need to mark the content using Urls as their identifier, and to that end we have a couple of way build-in into nRoute - though yet again, you have a flexible pass in that you can create your own loading/mapping strategy. My preference is normally to use attribute-based mapping system in nRoute owing to its simplicity (and which again like everything else you can customize/extend). Below, are some relevant snippets from the code-behinds of various content files, using attribute based mapping:

// Mapping in HomePage.xaml.cs
[MapNavigationContent("Home/", "Home Page")]
public partial class HomePage : UserControl { .. }

// Mapping in InformationPage.xaml.cs 
[MapNavigationContent("Pages/AboutInformation", "About")]
public partial class InformationPage : UserControl { .. }

// Mapping in FuturePageViewModel.cs
[MapViewModelViewNavigation("Pages/FuturePage/{Name}", 
	typeof(FuturePageViewModel), typeof(FuturePage))]
public class FuturePageViewModel { .. }
Using the MapNavigationContent attribute is one the simplest way to annotate content as Urls; as shown above we put it on the content type (in this case the HomePage class), and specify it's Url Identifier ("Home/") and optionally a static title ("Home Page") associated with that Url. The other attribute shown is MapViewModelViewNavigation which as evident is helpful when using the M-V-VM pattern, and therein we can associate the Url with the View type (in this case the FuturePage type) and its associated View-Model type (FuturePageViewModel type). Further, using this attribute the View-Model type is automagically injected into the View, by setting it as it's DataContext when the Url is requested for. Do note, you have flexibility as to where you put these attributes, see my other posts for examples.

The other build-in way to register is akin to what is present in ASP.NET 3.5sp1 or MVC, which is via statically registering against the NavigationService static class. Below, is an abbreviated snipper from the application class in the demo app:

protected override void RegisterNavigationsRoutes()
{
    NavigationService.MapLoadedAssembliesRoutes();
	NavigationService.MapRoute("Images/HeartYourWeb",
        new NavigationResourceHandler("Images/HeartYourWeb.xaml", NavigationResourceHandler.XamlLoader));
	...
}
Here the first call is actually to enable attribute based mapping (for all loaded assemblies), and there after we specifically map the route for a loose-xaml file using the Url Identifier "Images/HeartYourWeb". And as this is a resource in the assembly we use the NavigationResourceHandler to help with that. For more information on mapping navigation routes please see my other blog posts, however the big-picture take-away should be that mappings serve the function of abstraction, in this case abstraction of resources as Urls.

Content Navigation

Given the mappings, we can use the registered Urls to navigate to the content; and for most purposes I recommend using the extensive-set of behaviours in nRoute to avail navigation. Throughout the MasterPage you will see exclusive use of the navigation behaviours for content navigation, show below are some examples:

<!-- NAVIGATE ON MOUSE DOWN ON TEXTBLOCK -->
<TextBlock .. nav:MouseDown.NavigateUrl="Pages/FuturePage/Folders" />

<!-- NAVIGATE ON Ctrl+H KEY DOWN, note this is part of a Behaviours Collection -->
<bhv:KeyUpNavigate NavigateUrl="Home/" Key="H" KeyModifiers="Control" />
In the first case here, we attach the navigate behaviour to a TextBlock which on the (LeftButton)MouseDown event will navigate to the specified Url. And in the second case, we have attached another behaviour on the UserControl, that on recognizing the Cntrl+H key combo will navigate to the "Home/" Url. As you can see for the most part this is all pre-defined, however it doesn't have to be, you can also use the Url Address bar at the bottom of the MasterPage to manually navigate to any valid Url (try about:blank). I hope you can see how we at first abstracted the content via Urls, and using the same Urls also realized them visually.

State Management

In order to use the state management facilities in nRoute, one has to opt in using a simple interface called ISupportNavigationState - which is the case with the FuturePageViewModel type. As mentioned earlier this is the View-Model class backing the FuturePage.xaml, and the logic is trivially simple - all it does is provide a random brush (see OnChangeColour which is exposed by the ChangeColourCommand) from the application resources, and also saves/restores both the selected brush and any text entered by the user. It also makes use of tokenized Urls, as specified in the MapViewModelViewNavigation attribute, have a look:

[MapViewModelViewNavigation("Pages/FuturePage/{Name}", 
	typeof(FuturePageViewModel), typeof(FuturePage))]
public class FuturePageViewModel 
	: ISupportNavigationState, INotifyPropertyChanged { .. }
In the Url registered we have the {Name} token, which gives us the UI's title to display; this token-value pair is availed in the InitializeState method via its "state" parameter (a name-value dictionary). So a Url like "Pages/FuturePage/LightUpTheWeb/" will display "Light Up The Web" as its title in the page, try here. This is rather vain, but you could easily get in your OrderId or CustomerId via the Url and do something more constructive.

The second key construct here is the SaveState method that basically takes the two key properties (the selected colour and entered text) and returns it in a dictionary - which represents the state of the page. Now when you navigate onto the page (via either Back/Forward/New navigation manner) the StatefullContainer will restore the state by passing back the dictionary you saved earlier (as seen in the RestoreState method), and in this case we just use that to restore the two key properties. It is really very straightforward, and the benefit being that the visuals (and the View-Model in this case) don't need to be persisted in the memory, only the relevant state is stored and restored as required by the container.

Action De-Composition

In addition to the content composition and navigation, nRoute also features a set of functionality that allows you to address actionable code via Url identifiers; please refer to my actions related post for detailed information. In the Demo app, you will find trivial examples of how to use the Action infrastructure, the snippet below (from WorkspaceNextPreviousActions.cs) shows an action handler that allows you to select the next or previous workspaces/blade:

[MapActionHandler("Workspace/Actions/Previous")]
[MapActionHandler("Workspace/Actions/Next")]
public class WorkspaceNextPreviousActions : IActionHandler 
{
    public bool CanHandle(IActionDefination action)
    {
        return true;
    }

    public void Handle(IActionDefination action)
    {        
        var _viewModel = ((App)Application.Current).WorkspacesViewModel;
        var _newIndex = 0;

        .. // implementation details

        // we select a new workspace, note the use of the dispatcher
        action.Request.Dispatcher.BeginInvoke(() => _viewModel.ActivateWorkspace(_newIndex));
    }
}
The idea behind actions is to decompose your application's reusable code into a set of independent handlers, which are addressable in a loosely coupled fashion using Url. In the case above we mark the IActionHandler implementation with two Url Identifiers (see the MapActionHandler Attributes) that either select the previous workspace or the next workspace as per the requested Url. Also observe that Actions are consumed off the UI thread, hence the use of the dispatcher [Line 18]. What makes the investment of creating IActionHandler worthwhile is the structured but loosely-coupled way of consuming the exposed functionality, as show below:
<!-- NEXT PREVIOUS ARROWS -->
<TextBlock ToolTipService.ToolTip="Select Previous Workspace" ... 
           acn:MouseUp.ActionUrl="Workspace/Actions/Previous"  />
<TextBlock ToolTipService.ToolTip="Select Next Workspace" ... 
           acn:MouseUp.ActionUrl="Workspace/Actions/Next" />
As you can see here, we have basically attached behaviours to the TextBlocks which on (LeftButton)MouseDown event execute the action identified by the Url (without any direct reference to the handler). Another point to note if you try and execute an Action Url that isn't registered, it will raise an exception - this is design, because Actions per se have no visual component and without any indicator to their existence, calls might go unheeded which is an unacceptable outcome. So Urls in nRoute might be very loosely-coupled locators, but they are also structured and unambiguous as content/action providers (i.e. not magic-strings).


PART III: SUMMARY

Even though the demo app lacks substantial content, it demonstrates a range of features available in nRoute - however, beyond the technical ins-and-outs I hope what is also apparent is what nRoute brings to the table. From my perspective, nRoute sits in-between the infrastructure code and the actual consumable/actionable content, it bridges the chasm between the two - which in turn makes your code more adaptable and equally your infrastructure more changeable, largely independent of each other.

EDIT: added the State Management section

Posted by Rishi on 16-Apr-09 1:46 PM, 23 Comments

Categories: nRoute

Ok firsthand, let me qualify the title that this is "part of the vision". Now, you might have seen this great video of Microsoft's Vision for 2019 of what software and hardware might look like, and how we might interact with it in the future. It is really fascinating stuff, especially for a technology and UX enthusiast like myself. Anyway so, I wanted to create a demo app for my shiny new framework (which you can read up on other posts), and I kinda thought the kind of interactivity in the video is what my framework is all about - so I went out to replicate the UI using my little framework called nRoute.

Here are a couple of snapshot of the original UI, I referenced:MicrosoftVision2010
Snap1
 Snap2

I created the demo app with Blend 2 and Visual Studio 2008 (no Illustrator or Photoshop) in about 2 days - faster than I though I would. However, my work is rather preliminary, as I want to really develop on these concepts with Silverlight 3 and all the goodness that it brings. In fact, with the Silverlight 3 version of this app, I plan to feature much more of visuals shown in the original video (hello perspective 3D and multi-touch). Below are some grabs of my interpretation:

nRouteFutureDesktop1
nRouteFutureDesktop2
nRouteFutureDesktop3
Currently the application is very light on content, as it was primarily designed to showcase the technical marvels of the nRoute Framework ;) but given some time and inclination I think we can have a little piece of the future rather soon.

To run the demo click here (uses Silverlight 2) and for the source code visit http://nRoute.codeplex.com. BTW, I call this app the "Future Desktop".

UPDATE: for those technically inclined, this post goes over the nRoute-related features showcased in this demo app

Posted by Rishi on 02-Apr-09 2:24 PM, 53 Comments

Categories: General, nRoute, Technology