A discussion about Rich Internet Applications, and user experience focusing on architecture, design patterns and methodologies.

Showing posts with label Development. Show all posts
Showing posts with label Development. Show all posts

Saturday, April 17, 2010

Dictionarys in XAML

Short and simple post about how to declare and bind to a custom dictionary in Silverlight 4.  I had trouble finding a solid example of this since it has been properly introduced in the full release of Silverlight this past week.

Essentially I derived from Dictionary<String,String> and called it CustomDictionary within the application project.  Add a namespace declaration called local for the project and then:

<UserControl.Resources>
<local:CustomDictionary x:Name="dictionary">
<
sys:String x:Key="One">1</sys:String>
<
sys:String x:Key="Two">2</sys:String>
<
sys:String x:Key="Three">3</sys:String>
</
local:CustomDictionary >
</
UserControl.Resources>

<
Grid>
<
TextBlock Text="{Binding Source={StaticResource dictionary}, Path=[One]}"></TextBlock>
</Grid>



Quite simple really.  You bind to the dictionary resource and specify the key as the path.



Why do this?  I really like the idea of creating a dynamic and blendable ViewModel locator (thanks John Papa http://bit.ly/b11pUB) and I wanted to try my hand at doing this myself without the converter.



I’m planning on posting a blog on using MEF for composition and DI soon.  I think for smaller projects, it makes sense to keep it simple.  For larger projects, Unity might make more sense.

Monday, November 9, 2009

Unit testing in Silverlight with Rhino

I try to follow the test driven design approach but I find it very difficult to do when ramping up on new technology.  Having wrapped up the initial release of Reflect (my MVVM core library),  I decided to try my hand at writing unit tests for Silverlight.

The first step was to get the Unit Testing Framework up and running.  The first step was installing the templates (see http://code.msdn.microsoft.com/silverlightut).  I struggled with this a bit, but it ended up being very simple.  Put the SilverlightTestClass_CSharp.zip file in C:\Users\Carlos\Documents\Visual Studio 2008\Templates\ItemTemplates\Visual C# and the SilverlightTestProject_CSharp.zip in C:\Users\Carlos\Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C# (or the VB files as required).  Reload Visual Studio and the templates show up:

image

image

If you place them in a subfolder called Silverlight, they will appear in the Silverlight category.  I have not figured out how to have them appear in both without duplicating the zip file.

When you create a new test project, you will need to replace the references to the testing libraries Microsoft.Silverlight.Testing and Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.  Also, download Rhino for Silverlight here http://ayende.com/projects/rhino-mocks/downloads.aspx.  You will need to reference Castle.Core-Silverlight, Castle.DynamicProxy-Silverlight and Rhino.Mocks 3.5.Silverlight. 

From here on, its business as usual:

 

[TestMethod]
public void Navigator_goes_to_requested_page()
{
    Expect.Call(_Html.CurrentBookmark).Return(string.Empty);
    Expect.Call(delegate { _Html.NavigateToBookmark(ViewName); });
    _mock.ReplayAll();

    _navigator.RegisterPage<TestViewModelGeneric>(ViewName);
    _navigator.Goto(ViewName);

    _mock.VerifyAll();
    Assert.IsTrue(_RegionManager.Regions[RegionName].Views.Contains(_view));
    Assert.AreEqual(Visibility.Visible, ((View)_view).Visibility);
}

The framework runs the tests in a Silverlight App in a browser which is appropriate considering that is the environment you will probably be running your app, but I still haven’t wrapped my head around how I can run these tests for an continuous integration setup on a build server.

image

You can find the full source for Refract with unit tests here: http://refract.codeplex.com/.

Next Step

One of tests  runs synchronously on asynchronous code.  I was lucky that it passes, but it weighs on my conscience, so I will be using some of the built in test classes in the framework to write an asynchronous test.

Friday, November 6, 2009

MVVM library source code released.

I have released the source code with unit tests (half done) and a demo application on CodePlex.

You can find it here: http://refract.codeplex.com/

Thursday, November 5, 2009

Composite Silverlight

I’ve been on hiatus for a while working on a windows forms application using Composite Application Block (CAB) and the Model-View-Presenter pattern. This has inspired me in my Silverlight efforts as the modularity of the CAB architecture is enticing.

My first attempt involved trying to use Silverlight 3’s navigation application to navigate to pages defined in modules loaded at runtime but the navigation namespace does not lend itself to this. Instead, I decided to use PRISM’s (the new CAB for WPF and Silverlight) modularity namespace with a custom navigation implementation.

Prism

imagePrism is the code name for Patterns and Practice: Composite WPF and Silverlight application guidance (CompositeWPF). That’s quite a mouthful so Prism it is.

Similar to CAB, it provides core libraries for several design patterns like modularity, commanding, event aggregation and dependency injection. Unlike CAB, it is less intrusive and allows you to mix and match pieces as you wish to use them.

In a modular application, the main window (shell) contains regions that are placeholders for views. The bulk of the application is contained in modules (assemblies), which group code according to common functionality. The trick is that the modules are not referenced by the shell and do not reference each other, everything is abstracted. This allows modules to be developed and delivered independently of each other.

image

The infrastructure assembly contains utility classes and interfaces common to all assemblies in the solution. I like to use solution folders to organize my projects as follows:

image

Referencing the source code from the Prism libraries facilitates debugging and understanding. Again, the shell project does not contain references to the module projects, nor do the modules reference each other. All communication between these libraries is abstracted through Commands or the Event Aggregator. In the case of synchronous communication, a good approach is the register a service with Unity and exposing the interface in a common library.

Model-View-ViewModel

Model-View-ViewModel is a design pattern that allows us to separate the view from the business logic. The goal here is to minimize the amount of untestable code in the view. I go a bit further and put absolutely no code in my views.

I have added a Navigation namespace to my MVVM library to handle all things navigable. The navigator class allows modules to register pages and provides navigation functions for the shell. The interface is as follows:

public interface INavigator
{
void Clear();

void Goto(string pageName);

INavigator RegisterPage(string pageName, Type viewModelType, ICommand targetComand);

INavigator RegisterPage<TViewModel>(string pageName, ICommand targetComand) where TViewModel : ViewModel;

PageItemList PageItems { get; }
}

Modules can register their pages by calling the appropriate method:

public INavigator RegisterPage(string pageName, Type viewModelType)
{
PageItem pageItem = new PageItem(pageName, viewModelType);
_PageItems.Add(pageItem);
Container.RegisterType(viewModelType);
if (pageName == HtmlPage.Window.CurrentBookmark)
{
Goto(pageName);
}

return this;
}

This method stores the metadata for the page in a managed collection (internally a dictionary), and registers the ViewModel type with Unity. A page can be navigated by calling Goto:


public void Goto(string pageName)
{

PageItem navigatedPage = _PageItems[pageName];

if (navigatedPage == null)
{

throw new KeyNotFoundException("Page " + pageName + " not found in page list.");

}


Clear();

ViewModel viewModel = Container.Resolve(navigatedPage.ViewModelType) as ViewModel;

viewModel.Show(_mainRegionName);

_activeViewModel = viewModel;

HtmlPage.Window.NavigateToBookmark(pageName);

}

This finds the appropriate ViewModel, resolves an instance with Unity and adds it to the main region of the page. This also sets the “hash” value on the url to the name of the page to provide deep linking functionality.

Commands

In order for the shell to display a page, it has to tell the module controller (a class that initializes and manages the module) to display the page. The shell has no reference to the module, so it cannot instantiate a ViewModel or a view directly. All it knows is the page name. To provide a communication bridge, I chose commands (the event aggregator was the other choice). I wrapped the command into the Page metadata to simplify the logic and reduce repetitive code.

The page metadata is defined in a PageItem class and apart from storing the name of the page and the ViewModelType it also implements all necessary commanding functionality:

 
public PageItem(string name, Type viewModelType)
{
Active = true;
Name = name;

……
Command = new DelegateCommand<string>(Navigate, p => { return Active; });

}

In order to control the availability of a page, we can tap into the CanExecute event of the command:


public bool Active
{
get
{
return _Active;
}
set
{
_Active = value;
if (_Command != null)
{
_Command.RaiseCanExecuteChanged();
}
}
}

Modules

The module is loaded at runtime by the shell using a module catalog. The bootstrapper loads up the ModuleCatalog from a xaml file called ModulesCatalog.xaml:


protected override IModuleCatalog GetModuleCatalog()
{

return ModuleCatalog.CreateFromXaml(new Uri(“ModulesCatalog.xaml”, UriKind.Relative));


}

The catalog file lists the modules to load:


<Modularity:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:Modularity="clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">


<
Modularity:ModuleInfoGroup Ref="Navantis.Sports.Roster.xap"InitializationMode="WhenAvailable">

<
Modularity:ModuleInfo ModuleName="Navantis.Sports.Roster"

ModuleType="Navantis.Sports.Roster.RosterModule, Navantis.Sports.Roster, Version=1.0.0.0" />

</
Modularity:ModuleInfoGroup>


<
Modularity:ModuleInfoGroup Ref="Navantis.Sports.Schedule.xap"InitializationMode="WhenAvailable">

<
Modularity:ModuleInfo ModuleName="Navantis.Sports.Schedule"

ModuleType="Navantis.Sports.Schedule.ScheduleModule, Navantis.Sports.Schedule, Version=1.0.0.0" />

</
Modularity:ModuleInfoGroup>


</
Modularity:ModuleCatalog>


Each module project contains a class that derives from ModuleInit which acts as a controller for the module:


public class RosterModule : IModule

{

……


    public void Initialize()
{

Navigator.RegisterPage<HelloViewModel>("Hello", SayHelloCommand);
Navigator.RegisterPage<GoodByeViewModel>("GoodBye", SayGoodByeCommand);
}

#endregion
}

In the initialize method, the pages are registered on the Navigator. All that’s left is to set up a menu to allow the user to navigate to these pages. I have created a simple UserControl called menu which fills a stackpanel with a button for each page registered on the Navigator:


private void Build(IList pageList)
{
foreach (PageItem page in pageList)
{
Button button = new Button() { Content = new TextBlock() { Text = page.Name } };
Click.SetCommand(button, page.Command);
Click.SetCommandParameter(button, page.Name);
LayoutRoot.Children.Add(button);
}
}

The command parameter is the name of the page to navigate to.

Deep Linking

In order to enable deep linking, we need to do two things:


  1. Update the url whenever we select a new page

  2. Read the url when the app loads to select a specific page.

The first part is handled in the Goto method of the navigator:


HtmlPage.Window.NavigateToBookmark(pageName);


This will update the url by adding a hash (#page) to the end.

The second part is accomplished by checking the hash at startup. Unfortunately the modules are loaded as they become available (downloaded from the server) so we need to take a passive approach. As each page is registered, its name is compared to the hash, and when we have a match, we display it:


if (pageName == HtmlPage.Window.CurrentBookmark)
{

Goto(pageName);

}


What’s next

Currently the only menu possible is a single level one, no hiearachy. This could be accomplished by adding a group value to each page item indicating which node the page belongs to and letting the shell deal with constructing the hierarchy.

Also there is currently no way to indicate which page is selected on the menu. A binding would need to be established to allow this.

I plan on posting the source code to the MVVM library once I have cleaned it up and finished unit testing it.

Wednesday, June 24, 2009

Test Driven Development Introduction Video Released

I have just published a two part video of a presentation I gave to my colleagues, describing Test Driven Development using Visual Studio Team System and Rhino Mocks.

http://silverlight.services.live.com/71140/Test%20Driven%20Development%20Part1/video.wmv

http://silverlight.services.live.com/71140/Test%20Driven%20Development%20Part2/video.wmv

I hope this will inspire more people to adopt this beneficial pattern.

Thursday, October 23, 2008

User Group Presentation

So I just presented at the Toronto Silverlight User Group (http://www.torontosilverlight.com/) and Toronto .NET User Group (http://www.torontoug.net/) and thought it would be a good idea to share the material with everyone. 

I'd like to thank the user group hosts and all that attended for allowing me to rush through what is clearly much more content than a person can absorb in an hour or so.  I will be breaking the solution down again in more detail on this blog, so stay tuned.

Powerpoint and source code.

Wednesday, August 6, 2008

Silverlight LOB Architecture Design

<- User Experience for Line of Business    

A Silverlight application by its nature is a distributed app with a front-end on the client and a web service to provide connectivity to the data store.

image
Application Diagram

In order to decouple dependencies between components, I use dependency injection.  All components consumed by other components define a strong contract through an interface, making them replaceable and making unit testing simpler.  Since the front-end connection with the business logic is handled declaratively, no contract is required. 

Sample Application

For our working example, we have a straightforward requirement:

  • Display a list of users
  • Allow adding, updating and deletion of users

So we are defining a simple CRUD operation on an entity.  The following class diagram describes the different components needed to implement this using the Model-View-ViewModel design pattern.

 

image
Class Diagram

The view binds to the data model for interaction with the entities.  To handle user interaction, we will be binding to a component called "ViewModelAction" which encapsulates event handling and availability, similar to WPF commands.  The components are relatively lightweight and are focused on streamlining the binding process.  This allows the view contain absolutely no code.

The common functionality for these components is defined in a central library that could be re-used for other applications.  The View, Model, ViewModel and ViewModelAction base classes are all derived from a abstract class called Component which mainly implements property change notification through the INotifyPropertyChanged interface. 

Gotcha

One of the obstacles I ran into with declarative binding is that the visual designer attempt to instantiate all objects.  In the case of the model, this was bad as Visual Studio was attempting to connect to the web service and failing.  I added an "IsDesignMode" flag to component to wrap calls to external resources in my components.  This is the same solution to a similar problem in ASP.Net.

Up Next

I'm going to take a top down approach to subsequent blogs to keep my non-developer audience interested longer.  I will show how the view is defined in XAML, followed by the ViewModel (with kung fu action) and lastly the Model. 

Wednesday, July 23, 2008

User Experience for Line of Business

Background

I have long considered HTML to be a hindrance to user experience in business applications. This old "language" was designed for simple hypertext informational pages but patched and bandaged to support the ever-growing expectations of corporate clients. I was very excited to hear of Microsoft's new Presentation Foundation and have been working toward promoting it as a replacement to HTML for intranet style projects.

Crossroads

After much research, my path is chosen. I have focused my initial research on Silverlight for its flexibility and cross-platform support, but I plan on including WPF in my long-term efforts. I have also chosen Model-View-ViewModel (MVVM) as the design pattern for its intuitive elegance with Silverlight's declarative model. WPF has better support for some of the MVVM's architecture, so I have taken a simplistic approach to some of the challenges in order to keep the implementation relatively light-weight.

I have been inspired and guided by tutorials and blogs that I have seen, so thanks to the online community for the invaluable information they provide. Thanks to all.

Model-View-ViewModel

It basically states that modern design patterns follow a simple philosophy:

  • Applications implement a model that represent the data store. This is the "Model".
  • The "View" renders the display and allows users to interact with data.
  • Business rules and application workflow are handled by the "ViewModel". This component provides endpoints for declaratively binding to data and actions.

More on this here.

There is also an article by Dr. WPF about Model-View-Poo that I enjoyed.

Practice Application

I chose to build an administration module for a web application as a goal to work towards. Basically, it would display a list of users and allow editing of a user in a detail screen.

The solution plan would be as follows:

ProjectDescription
AdminThe Silverlight app., implementing the Views and View Models
ClientLibraryFunctionality shared between Silverlight apps. including the Model
DataServiceA WCF service providing database operations to the client
WebThe web application hosting the Silverlight apps.
BaseCommon functionality for all MVVM style solutions

Next Up

For my next trick, I'd like to describe the Base and ClientLibrary projects in detail. The Web and DataService are not really relevant for UX discussion, so I will not be getting into them.

About Me

My photo
Toronto, ON, Canada
I am a technical architect at Navantis, with over 12 years experience in IT. I have been involved in various projects, including a Hospital information system called CCIS for which my team received the 2007 Tech-Net innovation award. I have been working with Silverlight since beta 1, and am very keen on practically applying this technology and WPF to line of business applications.