ViewModel First – ViewCaching

With View model first approach, view are usually created via DataTemplate, and each time a view model is injected in the content control, the corresponding view is recreated.

If you have complex view where it take bit time to create view, you may see the performance hits. To avoid the performance hit you may want to cache the view and use the cached view when available. This can be done via creating CacheContentControl and you choice of view factory.

The basic idea is to wrap the view inside CacheContentControl and delegate the view creation logic to your view factory. The attached sample uses weakreference view factory,say if GC has not collected the view, you may use the cached view instead of creating view each time. This will work with controls like tab control docking controls etc.

The CacheContentControl  code

public class CacheContentControl : ContentControl
    {
        public CacheContentControl()
        {
            Unloaded += ViewCache_Unloaded;
            ViewFactory = WeakReferenceViewFactory.Instance;
        }

        void ViewCache_Unloaded(object sender, RoutedEventArgs e)
        {
            Content = null;
        }

        private Type _contentType;
        public Type ContentType
        {
            get { return _contentType; }
            set
            {
                _contentType = value;
               //  use you favorite factory
                Content = ViewFactory.GetView(value);
            }
        }

        public IViewFactory ViewFactory { get; private set; }
    }

In the DataTemplate, use the ViewCache, pass the type of the real view you want to use:

<DataTemplate DataType=”{x:Type moduleB:Panel3Vm}”>

<Border Background=”Green”>

<local:CacheContentControl ContentType=”{x:Type moduleB:Pane3 }” Margin=”5″/>

</Border>

</DataTemplate>

The example uses standard data template (red option) to demonstrate each time you navigate to panes the corresponding views are recreated with new hash code.

If you select CacheContentControl (green option) and navigate the view is only created once. If you click on button to collected the GC then view are created on navigation if they are claimed by GC.

Why ViewModel first ?

I prefer to use view model first approach. For many reasons:

  • Vms are your application containing most of logic apart from glue code in form of behaviors or triggers.
  • If you creates views then you are responsible for its life and cleanup code. You have to deal with threading and other issues which are difficult to test. On the other hand of you create vms and leave the view creation logic with WPF via data template.. you don’t have to worry about threading issue. And there will be better separation of concerns.
  • With vm first approach zero code behind.
  • With a project level isolation for view and vms you can restrict developers using view specific things like dispatcher in the view model leaving more cleaner and testable code base. I.e view project sprojec to vm. And vm project should not refer to any presentation lib.
  • If there is clear boundary between view and vm. Both can evolve and will be less fragile.
  • Allows more complete testing of logic to open new Views and ViewModels
  • Tends to be DRYer (don’t repeat yourself ) as applications get larger
  • View and ViewModel are more independent and can be worked on separately more easily.

For more details see attached source code (download and rename docx to zip)

ViewCache Source Code

RadDocking With Prism + Mvvm

Features

  • Support MVVM with Prism
  • Supports ViewModel First or ViewFirst Approach
  • Supports styling RadPane in xaml rather than DockingPansFactory
  • Code RadDocking – SourceCode

The XAML

  • Defiine the region names at RadPaneGroup level
  • Set Rad Panel Style via ItemContainerStyle
  • Bind Header property of RadPane with Title Property in View Model
 <Window.Resources>
 <Style x:Key="RadPaneFactoryStyle" TargetType="{x:Type telerik:RadPane}">
 <Setter Property="Header" Value="{Binding Title}"/>
 </Style>
 </Window.Resources>
 <Grid>
 <telerikDocking:RadDocking>
 <telerikDocking:RadDocking.DocumentHost>
 <telerikDocking:RadSplitContainer >
 <telerikDocking:RadPaneGroup regions:RegionManager.RegionName="MainRegion"
 ItemContainerStyle="{StaticResource RadPaneFactoryStyle}"
 >
 
 </telerikDocking:RadPaneGroup>
 </telerikDocking:RadSplitContainer>
 </telerikDocking:RadDocking.DocumentHost>

 <telerikDocking:RadSplitContainer InitialPosition="DockedRight">
 <telerikDocking:RadPaneGroup regions:RegionManager.RegionName="MainRegion1" >
 
 </telerikDocking:RadPaneGroup>
 </telerikDocking:RadSplitContainer>
 
 </telerikDocking:RadDocking> 
 </Grid>

Configure Region Adapter Mappings in Bootstrap

protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
 {
 var mappings = base.ConfigureRegionAdapterMappings();

 mappings.RegisterMapping(typeof(RadPaneGroup), this.Container.Resolve<RadPaneGroupRegionAdapter>());

 return mappings;
 }

Define the RadPaneGroup RegionAdapter

 
Behavior
public class RadPaneGroupRegionAdapter : RegionAdapterBase<RadPaneGroup>
 {
 public RadPaneGroupRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
 : base(regionBehaviorFactory)
 {
 }

 protected override void Adapt(IRegion region, RadPaneGroup regionTarget)
 {
 var docking = regionTarget.ParentOfType<RadDocking>();
 if (docking.DockingPanesFactory == null)
 {
 docking.DockingPanesFactory = new CustomDockingPanesFactory();
 }

 var store = DocumentsStoreAttachment.GetPanesStore(docking);
 if (store == null)
 {
 store = new PanesStore();
 DocumentsStoreAttachment.SetPanesStore(docking, store);
 BindingOperations.SetBinding(
 docking,
 RadDocking.PanesSourceProperty,
 new Binding("PanesSource") { Source = store });
 }
 }

 protected override IRegion CreateRegion()
 {
 return new SingleActiveRegion();
 }

 protected override void AttachBehaviors(IRegion region, RadPaneGroup regionTarget)
 {
 if (region == null)
 throw new System.ArgumentNullException("region");

 var docking = regionTarget.ParentOfType<RadDocking>();
 
 // Add the behavior that syncs the items source items with the rest of the items
 region.Behaviors.Add(RadPaneGroupSyncBehavior.BehaviorKey, new RadPaneGroupSyncBehavior()
 {
 HostControl = regionTarget,
 Docking = docking
 });

 base.AttachBehaviors(region, regionTarget);
 }

 private class PanesStore
 {
 public readonly ObservableCollection<object> Panes = new ObservableCollection<object>();
 ReadOnlyObservableCollection<object> _readonlyDocumentsList;
 public ReadOnlyObservableCollection<object> PanesSource
 {
 get
 {
 return _readonlyDocumentsList ??
 (_readonlyDocumentsList = new ReadOnlyObservableCollection<object>(Panes));
 }
 }
 }

 private static class DocumentsStoreAttachment
 {
 public static readonly DependencyProperty PanesStoreProperty = DependencyProperty.RegisterAttached(
 "PanesStore",
 typeof(PanesStore),
 typeof(DocumentsStoreAttachment),
 new PropertyMetadata(null)
 );
 public static void SetPanesStore(UIElement element, PanesStore value)
 {
 element.SetValue(PanesStoreProperty, value);
 }
 public static PanesStore GetPanesStore(UIElement element)
 {
 return (PanesStore)element.GetValue(PanesStoreProperty);
 }
 }

 private class CustomDockingPanesFactory : DockingPanesFactory
 {
 public RadPaneGroup ActiveGroup { get; internal set; }

 protected override void AddPane(RadDocking radDocking, RadPane pane)
 {
 var group = ActiveGroup;

 pane.SetValue(RadPane.HeaderProperty, DependencyProperty.UnsetValue);

 var style = group.ItemContainerStyle;
 if (style != null)
 {
 pane.SetValue(RadPane.StyleProperty, style);
 }
 group?.Items.Add(pane);
 }
 }

 private class RadPaneGroupSyncBehavior : RegionBehavior, IHostAwareRegionBehavior
 {
 public static readonly string BehaviorKey = "RadPaneGroupSyncBehavior";
 private bool _updatingActiveViewsInManagerActiveContentChanged;
 private RadPaneGroup _radPaneGroup;
 private PanesStore _documentStore;

 public DependencyObject HostControl
 {
 get
 {
 return _radPaneGroup;
 }

 set
 {
 _radPaneGroup = value as RadPaneGroup;
 }
 }



 public RadDocking Docking { get; internal set; }

 /// <summary>
 /// Starts to monitor the <see cref="IRegion"/> to keep it in synch with the items of the <see cref="HostControl"/>.
 /// </summary>
 protected override void OnAttach()
 {
 bool itemsSourceIsSet = _radPaneGroup.ItemsSource != null;


 if (itemsSourceIsSet)
 {
 throw new InvalidOperationException();
 }

 SynchronizeItems();

 Docking.ActivePaneChanged += ManagerActiveContentChanged;
 Region.ActiveViews.CollectionChanged += ActiveViews_CollectionChanged;
 Region.Views.CollectionChanged += Views_CollectionChanged;
 Docking.Close += _dockingManager_DocumentClosed;

 }

 private void _dockingManager_DocumentClosed(object sender, StateChangeEventArgs e)
 {
 foreach (var pane in e.Panes)
 {
 if (Region.Views.Contains(pane.Content))
 {
 Region.Remove(pane.Content);
 }
 }

 }


 private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 {
 if (e.Action == NotifyCollectionChangedAction.Add)
 {
 int startIndex = e.NewStartingIndex;

 foreach (var newItem in e.NewItems)
 {
 var panesFactory = ((CustomDockingPanesFactory)Docking.DockingPanesFactory);
 panesFactory.ActiveGroup = _radPaneGroup;
 _documentStore.Panes.Insert(0, newItem);
 }

 }
 else if (e.Action == NotifyCollectionChangedAction.Remove)
 {
 foreach (object oldItem in e.OldItems)
 {
 _documentStore.Panes.Remove(oldItem);
 }
 }
 }

 private void SynchronizeItems()
 {
 var store = DocumentsStoreAttachment.GetPanesStore(Docking);



 _documentStore = store;
 foreach (object view in Region.Views)
 {
 ((CustomDockingPanesFactory)Docking.DockingPanesFactory).ActiveGroup = _radPaneGroup;
 _documentStore.Panes.Insert(0, view);

 }
 }

 private void ActiveViews_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
 {
 if (_updatingActiveViewsInManagerActiveContentChanged)
 {
 return;
 }

 if (e.Action == NotifyCollectionChangedAction.Add)
 {
 if (Docking.ActivePane != null
 && Docking.ActivePane != e.NewItems[0]
 && Region.ActiveViews.Contains(Docking.ActivePane.Content))
 {
 Region.Deactivate(Docking.ActivePane.Content);
 }

 var pane = Docking.Panes.FirstOrDefault(x => x.Content.Equals(e.NewItems[0]));
 Docking.ActivePane = pane;
 }
 else if (e.Action == NotifyCollectionChangedAction.Remove &&
 e.OldItems.Contains(Docking.ActivePane))
 {
 Docking.ActivePane = null;
 }
 }

 private void ManagerActiveContentChanged(object sender, EventArgs e)
 {
 try
 {
 _updatingActiveViewsInManagerActiveContentChanged = true;

 if (Docking.Equals(sender))
 {
 var activePane = Docking.ActivePane;
 if (activePane != null)
 {
 var activeViews = Region.ActiveViews.Where(it => it != activePane.Content).ToList();
 foreach (var item in activeViews)
 {
 Region.Deactivate(item);
 }

 if (Region.Views.Contains(activePane.Content) && !Region.ActiveViews.Contains(activePane.Content))
 {
 Region.Activate(activePane.Content);
 }
 }



 }
 }
 finally
 {
 _updatingActiveViewsInManagerActiveContentChanged = false;
 }
 }

 }
 }

TPL Dataflow – Concurrent Programming

TPL DataFlow

TPL Dataflow is an in-process actor library on top of the Task Parallel Library enabling more robust concurrent programming.

Parallel computing is a form of computation in which multiple operations are carried out simultaneously.Parallel computing is closely related to asynchronous programming, using many of the same core concepts and support. Asynchronous programming is an approach to writing code that involves invoking operations such that they don’t block the current thread of execution.Many personal computers and workstations have two or four or 8 cores (that is, CPUs) that enable multiple threads to be executed simultaneously. Computers in the near future are expected to have significantly more cores. To take advantage of the hardware of today and tomorrow, you can parallelize your code to distribute work across multiple processors. In the past, parallelization required low-level manipulation of threads and locks.

The purpose of the TPL is to make developers more productive by simplifying the process of adding parallelism and concurrency to applications. The TPL scales the degree of concurrency dynamically to most efficiently use all the processors that are available. In addition, the TPL handles the partitioning of the work, the scheduling of threads on the ThreadPool, cancellation support, state management, and other low-level details. By using TPL, you can maximize the performance of your code while focusing on the work that your program is designed to accomplish.

Data parallelism refers to scenarios in which the same operation is performed concurrently (that is, in parallel) on elements in a source collection or array. In data parallel operations, the source collection is partitioned so that multiple threads can operate on different segments concurrently.

The Task Parallel Library (TPL) is based on the concept of a task, which represents an asynchronous operation. In some ways, a task resembles a thread or ThreadPool work item, but at a higher level of abstraction. The term task parallelism refers to one or more independent tasks running concurrently. Tasks provide two primary benefits:More efficient and more scalable use of system resources & More programmatic control than is possible with a thread or work item.

The concurrency models we has discussed so far have the notion of shared state (data) in common.Shared state can be accessed by multiple threads at the same time and must be thus protected, either by locking or by using transactions. Both, mutability and sharing of state are not just inherent for these models, they are also inherent for the complexities.Unfortunately, programmers have found it very difficult to reliably build robust multi-threaded applications using the shared data and locks model, especially as applications grow in size and complexity.Making things worse, testing is not reliable with multi-threaded code. Since threads are non-deterministic, you might successfully test a program one thousand times, yet still the program could go wrong the first time it runs on a customer’s machine.

We now have a look at an entirely different approach that bans the notion of shared state altogether. State is still mutable, however it is exclusively coupled to single entities that are allowed to alter it, so-called actors.The actor model in computer science is a mathematical model of concurrent computation that treats “actors” as the universal primitives of concurrent digital computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received.For communication, the actor model uses asynchronous message passing. In particular, it does not use any intermediate entities such as channels. Instead, each actor possesses a mailbox and can be addressed. These addresses are not to be confused with identities, and each actor can have no, one or multiple addresses. When an actor sends a message, it must know the address of the recipient. In addition, actors are allowed to send messages to themselves, which they will receive and handle later in a future step.

The Task Parallel Library (TPL) provides dataflow components to help increase the robustness of concurrency-enabled applications. These dataflow components are collectively referred to as the TPL Dataflow Library. This dataflow model promotes actor-based programming by providing in-process message passing for coarse-grained dataflow and pipelining tasks.The TPL Dataflow Library provides a foundation for message passing and parallelizing CPU-intensive and I/O-intensive applications that have high throughput and low latency. It also gives you explicit control over how data is buffered and moves around the system.

If you want to scale your application beyond single machine or process then ServiceBus (NServiceBus, Microsoft Azure, etc) are the best candidates. These are designed around message oriented architecture and you can achieve highly reliable, available and scalable application. As an architect i always focus on reliability, after all, a highly available and scalable service that produces unreliable results isn’t very valuable. – We will need another post to cover the in-depth of service bus..

TPL Dataflow (TDF) is a library for building concurrent applications. It promotes actor/agent-oriented designs through primitives for in-process message passing, dataflow, and pipelining. I have been playing with dataflow since its CTP was released and i found its very use in cases where you have to process data in form of a pipeline.With just few in-build blocks you can easily and quickly build concurrent app..

The primitive blocks provided by dataflow are

  • Buffering Blocks – Holds data for use by data consumers.
    • BufferBock(T) – FIFO queue of message that can be written to multiple sources or read from by multiple targets.
    • BroadcastBlock(T) – Used when you must pass multiple messages to another component.
    • WriteOnceBlock(T) – similar to broadcastblock except object can be written to one time only
  • Execution Block – call a user provided delegate for each piece of received data
    • ActionBlock(t) – calls a delegate when it receives a data – excepts synchronous or asynchronous delegates
    • TransformBlock(Tinout,TOutput) – call function delegates to transform the incoming message to another type- excepts synchronous or asynchronous delegates
    • TransformManyBlock(TInput , TOutput) – similar to TransformBlock except it can produce zero or more output values for each input value, instead of only one output value for each input value. – excepts synchronous or asynchronous delegates

Degree of Parallelism

Every ActionBlock<TInput>, TransformBlock<TInput, TOutput>, and TransformManyBlock<TInput, TOutput> object buffers input messages until the block is ready to process them. By default, these classes process messages in the order in which they are received, one message at a time. You can also specify the degree of parallelism to enable ActionBlock<TInput>, TransformBlock<TInput, TOutput> and TransformManyBlock<TInput, TOutput> objects to process multiple messages concurrently.

Now lets look at the implementation details of a web crawler

Request Buffer
|
PageDownload
/ Save     ParseLink
|
RaiseLinkFound

The messages to download a Url is received in the request buffer which is downloaded by a TranformBlock and converted into type safe page type message. The page message is then broadcasted using Broadcast block, which is further received by save ActionBlock and ParseLink Block. The parse link block parses the urls in the page and if they belong to same page it will raise an event for each url. The consumer of engine will receive the url and if its a new URL it will be posted back to engine.. The save action block will save the page to disk.

This is very basic example but you can see the message based approach is much more simpler than a shared resource + threading approach.

The TPL dataflow is good in case you don’t want to scale the solution beyond single machine as it offer a in process message base approach.With a proper service bus like NServiceBus you can scale out the solution beyond single machine and multiple servers could process the request to achieve the high throughput and off-course with easy to build,maintain clean code base.

In production there are more things you have to take care like logging, error handling, transactions, unexpected failure recovery, dependency injection,loosely coupled components, extensibility, scalability and so on.. Frameworks like NServiceBus provides all these features alone with API to handle more complex business problems.

Download Code : Here (Partially finished but working POC)

Cross AppDomain Tasks

As a part of plugin system, I build a framework that allows you to host plugins in current app domain, new app domain or external process host. The next channel is to run an long running task in new app domain and control it from any side of wire and here is the simple API with help of two classes..

public class RemoteTask : MarshalByRefObject
 {
 private readonly EventWaitHandle _completionEvent;
 
 public bool IsCanceled { get; protected set; }

 public bool IsCompleted { get; protected set; }

 public Exception Exception { get; protected set; }

 public bool IsFaulted { get; protected set; }

 public string Id { get; private set; }

 
 protected RemoteTask(CancellationToken cancellationToken)
 {
 Id = Guid.NewGuid().ToString();
 _completionEvent = new EventWaitHandle(false, EventResetMode.ManualReset, Id);

 cancellationToken.Register(() =>
 {
 IsCompleted = false;
 IsCanceled = true;
 Finished();
 });
 }

 public RemoteTask(CancellationToken cancellationToken, TaskAwaiter awaiter) : this(cancellationToken)
 {
 awaiter.OnCompleted(() =>
 {
 try
 {
 awaiter.GetResult();
 IsFaulted = false;
 IsCompleted = awaiter.IsCompleted;
 }
 catch (Exception exception)
 {
 Exception = exception;
 IsFaulted = true;
 }
 Finished();
 });
 }

 protected void Finished()
 {
 _completionEvent.Set();
 }

 public static void WaitWorker(RemoteTask worker)
 {
 var waiter = new EventWaitHandle(false, EventResetMode.ManualReset, worker.Id);
 waiter.WaitOne();
 }
 }

And class RemoteTaskOfT if you need results out from your task

public class RemoteTask : RemoteTask
    {
        public RemoteTask(CancellationToken cancellationToken, TaskAwaiter awaiter):base(cancellationToken)
        {
            awaiter.OnCompleted(() =>
            {
                try
                {
                    Result = awaiter.GetResult();
                    IsFaulted = false;
                    IsCompleted = awaiter.IsCompleted;
                }
                catch (Exception exception)
                {
                    Exception = exception;
                    IsFaulted = true;
                }
                Finished();
            });
        }

        public T Result { get; private set; }
    }

to use it from inside the new app domain
just return new RemoteTask(cancellationToken, task.GetAwaiter())
and on client side use
RemoteTask.WaitWorker(worker);
int result = worker.Result;
Exception ex = worker.Exception;

Asp.Net MVC flavours

The main purpose of the MVC (Model, View and Controller) architecture is to make separation of the business layer (logic) and the application layer (data)  from the presentation layer to the user. Model-View-Controller is a software pattern for achieving isolation between different application components. Its always desirable for software applications (especially web-based applications) that there must be clear separation between business logic and the user interface. A model represents the state of a particular aspect of the application. A controller handles interactions and updates the model to reflect a change in state of the application, and then passes information to the view. A view accepts necessary information from the controller and renders a user interface to display that information. Over past few years many version of ASP.Net MVC were release moving towards more and more mature framework for web development.Below is brief comparison of features release in each version

MVC 5 – October 2013

  • Bootstrap replaced the default MVC template.
  • ASP.NET Identity for authentication and identity management.
  • Authentication Filters for authenticating user by custom or third-party authentication provider.
  • With the help of Filter overrides, we can now override filters on a method or controller.
  • Attribute Routing is now integrated into MVC 5

MVC 4 – August 2012

  • ASP.NET Web API, a framework that simplifies the creation of HTTP services and serving a wide range of clients.
  • Follow to create your first ASP.NET Web API service
  • Adaptive rendering and other look-n-feel improvements to Default Project Templates.
  • A truly Empty Project Template.
  • MVC4 also uses Razor View Engine as a default view engine with some new features like condition attribute and ‘Tilde slash’
  • Based on jQuery Mobile, new Mobile Project Template introduced.
  • Support for adding controller to other project folders also.
  • Task Support for Asynchronous Controllers.
  • Controlling Bundling and Minification through web.config.
  • Support for OAuth and OpenID logins using DotNetOpenAuth library.
  • Support for Windows Azure SDK 1.6 and new releases.
  • MVC4 provides better support for Jquery like Jquery Mobile
  • Client side validation, Jquery validation and enhanced support for asynchronous methods
  • Supports many new features for mobile apps and also provides new mobile project template and default templates are refreshed and modernized

MVC 3 – January 2011

  • New Project Templates having support for HTML 5 and CSS 3.
  • Improved Model validation.
  • Razor View Engine (.cshtml for c# and .vbhtml for Visual Basic) introduced apart from Web Forms view engine (.aspx)
  • Having support for Multiple View Engines i.e. Web Forms view engine, Razor or open source.
  • Controller improvements like ViewBag property and ActionResults Types etc.
  • Unobtrusive JavaScript approach, Ajax and Client side Validation, Jquery Validation and JSON binding support
  • Chart, WebGrid, Crypto,WebImage, WebMail Controls
  • Improved Dependency Injection with new IDependencyResolver.It provides powerful hooks with Dependency Injection and Global Action Filters
  • Partial page output caching.
  • TempData, ViewData ,ViewBag
  • Supports not only Master Page but also Layout Page

MVC 2 – March 2010

  • MVC 2 uses only Web Forms view engine (.aspx) as a default View Engine.
  • (HTML Syntax) Web Forms view engine syntax: <%=Html code %>
  • TempData, ViewData
  • Jquery support is Good
  • Supports only Master Page
  • Client-side Validation and Asynchronous controllers
  • support controllers to process requests asynchronously
  • Supports validations using the RangeAttribute, RequiredAttribute, StringLengthAttribute, and RegexAttribute attributes.

MVC 1 – March 2009

MVC CTP – December 2007 

* Notes

  • View Engine is responsible for rendering of the HTML code from your views to the browser.
  • In ViewData, dictionary of objects are accessible via strings as keys
  • ViewBag was added in the C# 4.0 which uses the dynamic feature that allows to add properties of an object dynamically . We can say that ViewBag = ViewData + dynamic feature around the ViewData dictionary

Prism Navigation – ViewModel first

Navigating to view using prism navigation service is straight forward and there are lot of examples on web around this.With MVVM i always found ViewModel first approach as best because of lot of reasons, some of them are

  • With MVVM, ViewModels is your application
  • No threading issues as you will always create view models which can be created on any thread.
  • More responsive , you are not dealing with dispatcher context to create views and let WPF system decide when to create views.
  • No Memory leaks, The life cycle of views is controlled by WPF system in most efficient way
  • More testable application, Since you app lives in view models and they don’t have UI beasts,
  • And lot more..

This post cover a small trick to implement the ViewModel first navigation using Prism 5.0 for WPF.

1. What ever IoC you are using (the code is based on StructuralMap) expose the RegisterForNavigation<T> method and from module initialization, register interface of viewModels participating in navigation process. The RegisterForNavigation<T> will look like

public static void RegisterTypeForNavigation<T>(this ConfigurationExpression reg)
{
reg.For<object>().Use(() => ServiceLocator.Current.GetInstance(typeof(T)))
.Named(typeof(T).FullName);
}

And some where in module initialization you call this method

configurationExpression
.RegisterTypeForNavigation<ICustomerDetailViewModel>();

And to navigate to this view model just use

var parameters = new NavigationParameters { { "Activity", SelectedActivity }, { "ColumnName", columnName } };
var uri = new Uri(typeof(ICustomerDetailViewModel).FullName, UriKind.RelativeOrAbsolute);
regionManager.RequestNavigate(ShellRegions.Workspace, uri, parameters);

And obviously some where in you data template definition there should a (DataTemplate) mapping which WPF uses to swap the view model with corresponding view (and set data context too)..