Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Genesis Smart Client v2.0 - Ruby - User Experience Platform

4.50/5 (6 votes)
7 Jun 2010Ms-PL12 min read 25.5K   353  
This article introduces The Genesis Smart Client Framework v2.0 (Project Ruby). It focusses on the user interface component, dubbed the User Experience Platform (UXP), developed using PRISM for WPF and Silverlight.

Introduction

Over the last year, I have introduced my own C# smart client platform to everybody by releasing it as Open Source in a well documented and supported means. When I did this, the code was 5 years old and well aged. In order to stay with the times, and standards, I have been planning a from-the-ground-up rewrite of the platform. There will be NO backwards compatibility, however Genesis v1.0 will remain available online until the end of days.

During the development of Genesis v1.0, I decided that I was cleverer than everybody else and created my own standards for problems that arose during my hap-hazard development cycle. I've in turn mastered the arts of Configuration Management and Project Planning, and as with age, gained some wisdom. Genesis v2.0 has been in planning for more than a year with development work happening on much more fundamental levels to prepare for Genesis v2.0. I have stuck to standards and implemented Microsoft Patterns and Practices to ensure mass uptake of the new project, and also to enable a larger support base.

This article will detail all of the decisions I have made during the creation of the User Experience Platform (UXP) which enables multi-targeted development for WPF and Silverlight. The source code has been uploaded to CodePlex under change set 46607. It is available here. The WPF and Silverlight multi-targeting is thanks to the Patterns and Practices team at Microsoft for PRISM (Composite Application Library).

I will be making use of the latest source code release for Visual Studio 2010 and Microsoft .NET 4.0. I have also, while I am waiting for the official release of PRISM v4, included the DLLs for a custom .NET 4.0, VS2010 build of the Composite Application Library. I am aware that they released PRISM v2.2 a few weeks ago (as of June 2010), however they are still using .NET 3.5 for some libraries. My own build is 100% Microsoft.NET 4.0.

Design Considerations

PRISM

I have chosen PRISM (Composite Application Library) as the recommended practise of creating modules for Genesis v2.0. My main design considerations were to get rid of the intensive configuration required to load new modules into the Genesis v1.0 framework. PRISM has built-in support for an XAML based configuration file, with automatic downloading of missing files.

PRISM offered a mechanism for loading modules and creating Inversion of Control (IOC) containers. This enabled a much more modularized approach. I also found the methodology, backed by the Project Linker, useful for creating multi-targeted (WPF and Silverlight) projects with little trouble.

PRISM v4 looks promising, especially when considering the possibility of the Windows Phone 7 Series support.

Model View ViewModel (MVVM)

PRISM encourages the implementation of a proper Model View ViewModel (MVVM) pattern. My personal motivation behind the MVVM pattern, thanks to my very first Silverlight application that I developed during January 2010. I failed to apply the MVVM pattern and development quickly turned into a maintenance/'figuring out what is happening between all of the bindings and random RIA (beta 2) queries' nightmare.

During February, I perfected a new design using MVVM and found it to be much more predictable and controlled during application execution. I also got rid of RIA, we'll talk about that now.

RIA is Pure Evil

I'm not bashing RIA, in fact I think it is quaint, but nothing more. It cannot be considered to be a serious or a reliable platform for developing anything. That is if you even get past development. I say RIA is evil because on the surface, it is all friendly and pleasant. It lulls you into a false pretence that things will be easy, even though, in your gut you know, since you cannot figure out what black magic is happening in its belly, that it is going to turn around and bite you right in the keister!

Microsoft has done magic with RIA for VS2010, my experiences were based on VS2008. I now have a deep understanding of how RIA performs its stage show, enough so that I decided to implement a concept that I've been developing for a pure WPF version of Genesis v2.0 to work with Silverlight as well. After achieving the goal, I decided to add support for Silverlight in Genesis v2.0 and to use the Composite Application Library.

NetTiers

NetTiers? Not possible, I hear you say! I believe that most people have a great experience with NetTiers, and many people hate it to their core. I found NetTiers to be a good implementation of a service based data layer. With a bit of tweaking and integrating online templates, I massaged the templates into a WCF service and WF4 Workflow enabled code generator.

I ditched all of the Web Forms, Web Admin and Windows Controls stuff and focused on delivering Entities to my XAML bindings through WCF. I also developed templates that generated WF4 Workflow Activities for each method that NetTiers generates code for (such as the CRUD Insert, Update, Delete, GetAll, GetByPrimaryKey, GetByForeignKeys, etc.). These activities would use the WCF Client Proxy to connect to the WCF server. I also included some nice Activity Designers to make working with the Workflows easier.

By using a Workflow Service application, I can serve the Workflows via WCF to both WPF and Silverlight. The bad news is that this article does not cover any back-end code since I've only written the user interface. I'll cover back-end in the next article.

3rd Party Libraries

As those of you who have been following the evolution of the free Open Source version of Genesis v1 know, the default user interface used to be based on the DevComponents Ribbon. I removed all of the license keys from the code and shipped the Demo library. After many months, I removed all references to the library, and posted a version based purely on standard .NET controls.

This version is built from the ground up using nothing but the standard .NET components that each and every one of you should have access to by using Visual Studio 2010 and Microsoft.NET 4.0.

Architecture

The User Experience Platform (UXP) for Genesis v2.0 - Ruby consists of a Shell, an Infrastructure library and a View library. In the StockTraderRI PRISM sample and in all recommendations, the Shell contains the main window with all of the Regions configured. I found this to be very limited and implemented a mechanism to load the main window just as you would load a normal module. This means that you can ship your own main window so that you are not restricted to what I consider good design practise. This is the purpose of the View module. I will elaborate on the code changes later in this article when I discuss each module.

The use of PRISM relieves me of creating the module management framework and enables a broader uptake from familiars in the community, and good support for new developers. It is also an accepted standard amongst many enterprise developers and is founded in research done by Microsoft's Patterns and Practices. It would also seem as if everybody learnt from the Composite Application Block (CAB) and Smart Client Software Factory (SCSF) patterns. PRISM is light weight, adding no more than 300KB to the total overhead. The code requirements during the normal development cycle are also nearly transparent and non-intrusive.

Unit Testing also featured high on the list of requirements, and again PRISM came to the rescue aided by MVVM. PRISM with MVVM made it possible for easy Unit Testing, mocking and User Interface testing automation. Mocking is done with the help of Moq.

Source Code

The source is divided into Desktop (WPF) and Web (Silverlight), each with sub-divisions of Infrastructure, Modules, Shell and Unit Tests. I make use of the Project Linker (available on compositewpf.codeplex.com) to link the Silverlight projects to the WPF projects. The Project Linker automatically links files that are created/modified in the WPF projects to the equivalent Silverlight projects. Any files that include .Desktop or .Silverlight would not be replicated out of its parent project.

The source code has been uploaded to Code Plex under change set 46607. It is available here.

Infrastructure

002.png

The first project is the BlueMarble.Genesis.Infrastructure project. It includes all of the basic functionality that is common and shared across all levels of the application. This means that each module must reference this project to function properly within the context of the composite application. I have copied some functionality from the StockTraderRI sample application shipped by the Composite Application Library team. This is to ease the process of multi-targeting. They've already thought about many obstacles that multi-targeted developers will face.

In the Dark Orange highlight, you will see the folders and files that make up this library. In the Light Orange highlight, you will see the Silverlight equivalent project. It matches the WPF project file for file except where there is .Desktop or .Silverlight in the filename.

The Backgrounds folder contains some dynamic background templates that I've been working on. Currently for Genesis v2.0 - Ruby, there is only the Default background. This background includes an XAML image of Ruby (my parrot), Information Ambience which transitions text into and out of view, and the Background itself which combines the two components into a single control reference.

The Behaviors folder contains code to handle the behavior of multiple components of the composite application, including how Dialogs are displayed. Specifically there are .Desktop and .Silverlight files included in this folder to deal with differences in showing a client window via WPF and Silverlight. Most of this code has been copied from the StockTraderRI sample since they deal with consistency between WPF and Silverlight.

The Converters folder contains common converters that could be used by many types of projects. None of these are specific to the User Experience Platform's function.

The Interfaces folder contains the interfaces used by the modularized main window View. This includes IShellView and IShellViewModel which are normally found in the actual Shell application. I've moved them here to enable the main window with the main Region layout to be delivered through a module. This opens up the Shell to be completely generic in the application that it renders, which encourages reuse inside of development teams. I found that if I had to recreate all of the steps mentioned for each application idea that I had, I would not implement PRISM and full MVVM. Now I have a framework where everything can be quickly and easily determined by mere modules.

The Resources folder contains all of the resources for the Infrastructure library, this includes the basic Region Names. Again I have deviated from the recommendations by using a standard Resource File instead of a static class. I did this to encourage globalization and localization of the entire framework. The Helpers folder contains a wrapper for the Resources so that they can be bound in XAML.

Files in the root of the Infrastructure project contain global error/warning suppression, validation exception management, a visual tree helper. I've modified the Observable Command implementation to allow for the implementation of the same Commanding system to be used by both WPF and Silverlight.

IShellView.cs

C#
namespace BlueMarble.Genesis.Infrastructure
{
    public interface IShellView
    {
        void ShowView();
    }
}

IShellViewModel.cs

C#
using System.Windows;

namespace BlueMarble.Genesis.Infrastructure
{
    public interface IShellViewModel
    {
        IShellView View { get; }

        DependencyObject ShowView();
    }
}

Shell

004.png

The second project is the BlueMarble.Genesis.Shell project. It includes the basic functionality that is required to load all of the modules and to display the main window.

In the Dark Orange highlight, you will see the folders and files that make up this library. In the Light Orange highlight, you will see the Silverlight equivalent project. It matches the WPF project file for file except where there is .Desktop or .Silverlight in the filename.

The Bootstrapper folder contains the Unity Bootstrapper. This code is responsible for loading the modules and showing the main window. It is called from the App.xaml.cs file. In the screenshot, you can see ShellBootstrapper.Desktop.cs. This file contains functionality specific only to the WPF platform and will NOT be linked to the Silverlight project. This file specifically contains functionality relating to how the WPF client handles exceptions using the Enterprise Library.

The Converters folder contains converters required for the Shell to operate properly.

The Resources folder contains various resources required by the Shell, including the Error Strings and other localizable content.

ShellBootstrapper.cs

C#
protected override DependencyObject CreateShell()
{
    return null;
}

I have modified the CreateShell method to simply return null to separate the Main Window from the Shell.

App.XAML.cs

C#
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

#if (DEBUG)
        RunInDebugMode();
#else
        RunInReleaseMode();
#endif
        this.ShutdownMode = ShutdownMode.OnMainWindowClose;
    }

    private static void RunInDebugMode()
    {
        UnityBootstrapper bootstrapper = new ShellBootstrapper();
        bootstrapper.Run();
    }

    private static void RunInReleaseMode()
    {
        AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;
        try
        {
            UnityBootstrapper bootstrapper = new ShellBootstrapper();
            bootstrapper.Run();
        }
        catch (Exception ex)
        {
            HandleException(ex);
        }
    }

    private static void AppDomainUnhandledException
		(object sender, UnhandledExceptionEventArgs e)
    {
        HandleException(e.ExceptionObject as Exception);
    }

    private static void HandleException(Exception ex)
    {
        if (ex == null)
            return;

        ExceptionPolicy.HandleException(ex, "Default Policy");
        MessageBox.Show
	(BlueMarble.Genesis.Shell.Resources.ErrorStrings.UnhandledException);
        Environment.Exit(1);
    }
}

Main Window View

003.png

The third project is the BlueMarble.Genesis.View project. It includes the main window that the Shell is supposed to display. The purpose of this is to enable developers to design their own main window with the Region layout as they require. Developers are not tied into using the Region layout that I predetermine.

In the Dark Orange highlight, you will see the folders and files that make up this library. In the Light Orange highlight, you will see the Silverlight equivalent project. It matches the WPF project file for file except where there is .Desktop or .Silverlight in the filename.

The ShellView.Desktop.xaml file is specific to the WPF platform, and in the Silverlight project an equivalent ShellView.Silverlight.xaml file exists. This file contains the base XAML layout of the Main Window for this application. The ShellView.Desktop.xaml.cs file implements the IShellView interface from the BlueMarble.Genesis.Infrastructure library.

The ShellViewModel.cs file contains the ViewModel for the Main Window. The ShellViewModel.cs file implements the IShellViewModel interface from the BlueMarble.Genesis.Infrastructure library.

The ViewModule.cs file contains the module logic and handles loading the Main Window when the application starts.

ViewModule.cs

C#
public class ViewModule : IModule
{
    private readonly IUnityContainer container;
    private readonly IRegionManager regionManager;

    public ViewModule(IUnityContainer container, IRegionManager regionManager)
    {
        this.container = container;
        this.regionManager = regionManager;
    }

    #region IModule Members

    public void Initialize()
    {
        RegisterViewsAndServices();

        IShellViewModel shellViewModel = this.container.Resolve<IShellViewModel>();

        shellViewModel.ShowView();
    }

    protected void RegisterViewsAndServices()
    {
        this.container.RegisterType<IShellViewModel, ViewModel>();
        this.container.RegisterType<IShellView, Shell>();
    }

    #endregion
}

The ViewModule.cs file is the controller for the View Module, it is responsible for registering the Shell View and Shell ViewModel in the IoC container. After registration, it creates a new instance of the Shell ViewModel and calls the ShowView method.

C#
public DependencyObject ShowView()
{
    View.ShowView();

    return View as DependencyObject;
}

WPF Window

Image 4

This image represents the output from the WPF application.

Silverlight Window

Image 5

This image represents the output from the Silverlight application.

In both applications, the animations fire correctly and the user is presented with a user interface. This concludes the User Experience Platform (UXP) for The Genesis Smart Client Framework v2.0 (Project Ruby). In the next article, I will add the business logic required to link up the user security system, and the database to store each users' settings and rights.

Updates

  • 3 June 2010 - Published original article
  • 7 June 2010 - Updated article with code samples and more specific file descriptions

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)