Combining Silverlight Navigation Framework and Prism to create MVVM Applications – Introduction
This is introductory post for a series of posts where i will try to tackle the holy grail of MVVM applications – Navigation.
To do this I will be using Prism from Microsoft’s Patterns and Practices team (Silverlight version – latest drop) combined with Silverlight Navigation Framework and i will build small navigation framework on top of that.
If you are too busy to read this post and just want to see the result take a look at the current state of the sample Silverlight Prism Navigation application where you can see most of the important features of this small navigation framework (PrismExtensions.dll that contains all the framework code is 35.5 KB in size).
And for those of you with stronger nerves here is the real story:
Lately i have been playing with my old friend Prism and re-discovering how good it is for building MVVM Silverlight and WPF applications.
Out of the box you get a lot of things (and only few months ago i was trying to build all of this from scratch – you can see that from my earlier MVVM blog posts).
One of the things i like the most in Prism is the modularity concept and support for loading application modules dynamically from local/remote servers – on users/application request.
This allows developers to cut the application in modules with isolated functionality and on start load only mandatory parts and then load other modules only if users really needs/request them.
What really surprised me is that nobody has so far managed to combine Prism with Silverlight’s excellent Navigation Framework in a successful way so that is usable for real-life MVVM applications (at least i could not find any good examples on the web).
Prism has a concept of Regions and allows easy loading of Views into them but this is where it ends – there are no higher level concepts of navigation – this is why i decided to build some kind of Navigation framework on top of Prism – to fill that gap.
This is where the very important concept of Deep Linking comes into the story. I cannot imagine any serious Silverlight application without allowing users to bookmark pages in the browser, and to use the Back and Forward browser button to navigate though the UI, to manually ‘hack’ the URLs to load different data etc…
So this is something where Silverlight Navigation Framework can help us. It has built in support for all major browsers for browser history, it notifies the application about the browser URL change, there is HyperlinkButton control that has NavigateUri property where you can specify the application URL that will be loaded when user clicks on it (without full page reload off course – because only the fragment of the URL after # sign is changed) etc.
The only problem is that there is no easy way to combine Prism and Silverlight Navigation Framework.
Yes we can implement INavigationContentLoader and plug it into the Frame control but still we don’t have full control over the page/view loading process, we need additional Frame for each Region where we want to show Views etc.
So i decided to do a little research on how to simplify things and to create a small framework for Prism that will use Silverlight Navigation Framework to load Views into Prism Regions and enable Deep Linking, passing parameters to views, to allow integration with Prism modularity and allow deferred module loading etc – in other words all the features that one would expect to have in modern RIA Silverlight application.
Here are some features that i already support or will in near future:
- it must be a simple (for the end user-developer) but full blown Navigation Framework for Prism Silverlight MVVM applications
- it will support this main MVVM scenario: application will have one Main View (so called ‘Shell’) that will be loaded on start of the application and this will be the main ‘screen’ of the application that will have multiple regions where we can load Views. Only one region will be considered as Main Region and it will be ‘tied’ to the URL typed in the browser. Other regions will not update browsers URL or be affected by changes in the URL but application will be able to load Views into other regions – for example Widgets etc (i decided not to support Regions inside Views loaded into Regions on Main Region as this greatly simplifies the implementation and i don’t see a real usage scenario anyway - instead of using Sub-Regions you can always use child Views inside of your View for that).
- support for passing the parameters to the Views via browsers URL – every update in the URL of the browser will load appropriate view in Main Region (and pass parameters from URL to the Views ViewModel) and on the other hand, if some View is loaded to Main Region from code, this will reflect on the browser URL (including the parameters passed to View).
- when View is loaded into region it will be connected to its ViewModel (set as its DataContext) – this is done automagically by the framework, user just needs to define the mapping between Views and View Models in the Module initialization – more details on that in later posts.
- support for manually loading Views from ViewModels via code (not only via URLs) using the same framework – via some service like IPrismViewLoadingService
- framework should include support for Prism deferred loading of application Modules – there should be easy way to load Prism Modules that are marked as OnDemand and they should be loaded either manually – from code or automagically – when user navigates to URL that should show View that is in module marked as ‘OnDemand’
- there should be a way to define User Friendly URL’s – aliases for specific Views and Modules but some smart defaults should work out of the box by default like: “/Products/Detail/1234″ or “/ProductsModule/Details/1234″ etc – user should just type the URL in browser and Framework must load the Module if needed and then show the View (bound to its initialized ViewModel)
- full support for navigation between Views using HyperlinkButton controls – for loading Views to Main Region and to other Regions
- framework should be ‘opinionated’ regarding the way how it initializes and binds Views and their ViewModels – in our case it will be View-ViewModel-Marriage approach: there is separate service that initializes ViewModel and set it as DataContext of the View.
- it should be simple to use for the end user-developer – smart defaults should work without any user configuration yet customization should be possible for advanced scenarios
- whole solution should be based on services that implement defined interfaces – so that they can be easily changed with different implementations that user could plug via IOC – for example to easily change the parameters format from ‘parameterA/value1/parameterB/value2′ into ‘?parameterA=value1¶meterB/value2′ etc.
So this features should be enough to get us started but we can change this along the way if we see that its appropriate – if you have some suggestions – do let me know!
As you can see from the Sample Application I already have implemented most of these features and I will be finishing along the way as i write more posts in the future – what you can see in the demo right now is: Browser URL history integration (Deep Linking and Back/Forward buttons support), Loading Views with their corresponding ViewModels to Main Region and to secondary Regions, passing parameters to Views, asynchronous deferred loading of Modules/Views etc.
If some you know of some other Prism Navigation Framework that already has most of these features please let me know so i can stop doing this and enjoy real life
Otherwise see ya soon in the next part of this article series where i will explain all about this framework and share some code with usage scenarios.