Geeks With Blogs
Mike Kenyon Hoarked

I’m always happier in my Agile mentality with having something up and running that I can hit F5 on and see the fruits of my labor and this is no different.  So, the next thing we need to do is get a basic Prism application up.  The most basic Prism app in the world has three things in its .exe.

  1. The Application object, which sets up the bootstrapper object.
  2. The Bootstrapper object, which kick-starts the IoC container, loads modules and starts the shell.
  3. The Shell window (which I really wish began with a “C” so I could do an ABCs joke) is the display husk in which all other content in the application will be housed.

Let’s look at each individually and make some choices about them.

Application Object

Ironically, that which is most important in traditional WPF applications may be completely unimportant here.  The code for an application object might as well be a template.  The following steps will ALWAYS result in you having an appropriate application object in a Prism app.

  1. Open up App.xaml and remove the StartupUri attribute.
  2. Open up App.xaml.cs and replace the constructor with the one below.
public App() {
    Bootstrapper bootstrapper = new Bootstrapper();
    bootstrapper.Run();
}

You’re done.  We haven’t defined the Bootstrapper yet, but we will.  That was easy.

One minor thing that’s a fall-out here is that the resource dictionary from application is inaccessible.  This means that if you want to do global resource swapping you’re doing it on the Shell.

Bootstrapper Object

The bootstrapper component has the job of doing all the start-up stuff associated with the application.  It’s home to the composition container, loads and initializes all of the modules and, in short, causes all good things to happen.  It also requires choices.

The IBootstrapper interface gives you the typical steps and you can go through and implement on without too much problem.  The principal reason to do so is some preference on a composition container.  With the advent of the common service locator, most of what I want out of a container is behind a wall and I don’t care.  To that end, I don’t see why I should spend time implementing something new to get a choice in something I should (hopefully) never see.  Hence, for the sake of discussion here, I’m going to take the default which is the Unity container from the EntLib folks. 

So we’re going to make a class called Bootstrapper that derives from the UnityBootstrapper class.  Doing so requires that I implement one pure-virtual (abstract) method, CreateShell().  Here’s my implementation.  Barring needing to do something funky, this is also template code.  The creation of the shell through the container is not expressly necessary, but it’s mighty convenient for getting the system to resolve dependencies for you.

protected override System.Windows.DependencyObject CreateShell() {
    Shell shell = Container.Resolve<Shell>();
    shell.Show();
    return shell;
}

This is, however, also the time to decide how you want to modularize your application.  Modular apps are broken into, shockingly, modules.  Each module is going to load some services for others to consume, play a part in UI composition and have a chance to integrate itself with the rest of the application.  Traditionally, modules are bundled one to the DLL, but they’re no requirement for this.  Instead, the system uses an object called the module catalog to load each of the different modules.  Prism comes with loaders that work off of configuration files, reflection and just hard-coding it.  Heck, if you’re willing to cannibalize from SCSF, you can get one that does a web-service lookup call pretty quickly.  My personal favorite has always been one that does a directory scan with reflection.  This gives me the feel of Adobe Photoshop – a shell of an application with 90% of it’s functionality loaded from plug-in files.  Is it really necessary here, no … but it gets us into the feel of Prism, so I’ll use it.

protected override Microsoft.Practices.Composite.Modularity.IModuleCatalog GetModuleCatalog() {
    return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}

This creates a module catalog which will scan the application root for a “Modules” directory and will load and initialize any module in there.

All of this has added a couple of dependencies:

Composite UI – Microsoft.Practices.Composite.Desktop & Microsoft.Practices.Composite.Presentation.Desktop

Composition – Microsoft.Practices.ObjectBuilder2,  Microsoft.Practices.Unity, Microsoft.Practices.Composite.UnityExtensions.Desktop

Services – Microsoft.Practices.ServiceLocator

That’s the framework.  if you were using a different composition container, you could swap that stack for the one provided.

Shell Window

This is the root window of the application.  By requirement, there aren’t any.  It could be just a traditional window and be done with.  I’m going to make a couple of configuration changes here.  I’m looking for the kiosk look-and-feel, so I’m going to set WindowState to Maximized and WindowStyle to None.  This gives me a screen that coats whatever monitor it goes up on without any window chrome.  Perfect.  I’ll still give it a title even though it won’t appear in the non-existent chrome because if you swap off of the window, it’ll still be listed in the task bar and window list that way.

A word on resources.  I’m a big fan of keeping most stuff in resources whenever possible.  It gives me flexibility and styling avoids display lock-in later. Opposing that, it gets hard to find things, so I’m a fan of storing everything in one place, so I break up the resource list into a series of resource dictionaries, by type or resource and stow them each off separately.   I organize it by typed (default) resources up top and named resources below, in alphabetic order.  Here’s my definition of the resource dictionary at this point.  Over time I’ll have to templatize more things, but right now, panels (which I include windows into) are about it.

<Window.Resources>
     <ResourceDictionary>
         <ResourceDictionary.MergedDictionaries>
             <ResourceDictionary Source="Panels.xaml" />
         </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>
</Window.Resources>

By default windows start out holding a grid and I’m not going to change that.  One of the real failings of the WPF grid is that you can’t store the row/column definitions in a style themselves.  There is no ControlTemplate for a Grid nor can you create an object of RowDefintionCollection or ColumnDefinitionCollection.  I’m going to create the grid as a 2x2, with the top row autosizing and a 50%/50% split vertically.  In the upper-right corner, I’m going to drop an ItemsControl.  I’m going to need a way for people to swap between the modes and this is the easiest one I can think of.    I like using ItemsControl because I don’t know how I want to have it look right now and this way I can defer selection to a later date and time through styling.  I’m going to give it a style tag of “ButtonPanel” and move on.  In the entire lower row, I’m going to add a ContentControl.  This will hold the current display view for whatever the user is doing.  I’m going to give it a style tag of ContentZone and turn my mind to more interesting matters.

Regions

We’ve got places to put content, but we don’t currently have any way to get content into it.  Prism supports two different mechanisms for doing this.  Both involve the use of a region, which is defined most simply as a place that you can put content.

View Discovery – Involves the region “finding” the views that should fit into it.  It’s the easiest to use and the default mode.  Since the list of modules is going to be static and not based on user-action, we’ll use discovery for populating it.

View Injection – Involves an external entity “shoving” content into a region.  This is best used when the view is contextual in nature.  Since the bottom is going to have views that represent specific movies and categories, it makes sense that we inject into it. 

In both cases, all we have to do at this stage is specify a region name with an attached property (which I’m doing through styling).  Next stop, getting some basic content.

If you're interested here's the Project So Far

Posted on Wednesday, January 28, 2009 10:30 AM | Back to top


Comments on this post: Creating a WPF Application With Prism v2 – Shell

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © hoarked | Powered by: GeeksWithBlogs.net