<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:thr="http://purl.org/syndication/thread/1.0">
    <title type="text">Paul Stovell</title>
    
    <link rel="alternate" href="http://www.paulstovell.com/" type="text/html" />
    <subtitle>Paul Stovell's thoughts on WPF and client architecture.</subtitle>
    <updated>2009-11-15T22:58:04Z</updated>
    <id>http://www.paulstovell.com/feeds/rss</id>
    <creativeCommons:license>http://www.creativecommons.org/licenses/by-nc/2.5/rdf</creativeCommons:license>
    

    <link rel="self" href="http://feeds.feedburner.com/paulstovell" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
        <id>http://www.paulstovell.com/magellan-installer</id>
        <title type="text">Magellan Installer</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-installer" />
        <published>2009-11-15T15:05:07Z</published>
        <updated>2009-11-15T15:05:07Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;&lt;a href="/magellan"&gt;Back to: Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Magellan now comes with a Visual Studio Project Template that you can use to get started with quickly. You will need Visual Studio 2008. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://get.paulstovell.com/Magellan/Magellan-Setup.msi"&gt;Magellan-Setup.msi&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;h1&gt;Setup&lt;/h1&gt;

&lt;p&gt;&lt;img src="/get/magellan/installer-welcome.png" alt="Magellan Installer" /&gt;&lt;/p&gt;

&lt;p&gt;During the installer you will be prompted to install the Visual Studio project templates:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/installer-prompt.png" alt="Magellan installation prompt" /&gt;&lt;/p&gt;

&lt;p&gt;If Visual Studio is already running, your will be prompted to close it at this time. The project templates will be installed and Visual Studio updated.&lt;/p&gt;

&lt;p&gt;Once the installer finishes, your installation directory will contain the Magellan assemblies (in the &lt;em&gt;Public&lt;/em&gt; directory), plus supporting files for the project template:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/installer-directory.png" alt="Explorer" /&gt; &lt;/p&gt;

&lt;h1&gt;Creating Projects&lt;/h1&gt;

&lt;p&gt;In Visual Studio under the Windows node, you will now have the ability to create a Magellan project:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/new-project.png" alt="New Project" /&gt;&lt;/p&gt;

&lt;p&gt;Before the project is created, you will get a chance to decide whether to create unit tests, and how to handle the Magellan references. &lt;strong&gt;Magellan is not installed into the GAC&lt;/strong&gt;. You can either reference the assemblies directly from the installation directory, which will mean other developers also need to install the MSI, or you can have the project wizard copy the assemblies locally (the default option):&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/new-project-prompt.PNG" alt="New Project Prompt" /&gt;&lt;/p&gt;

&lt;p&gt;When the project wizard has finished, you will have a new Magellan project - it should compile and run first try and the generated test should pass.&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/new-project-solution-explorer.png" alt="The Solution Explorer" /&gt;&lt;/p&gt;

&lt;p&gt;You can also set up the same project manually without using the MSI. See the &lt;a href="/magellan-quickstart"&gt;manual quickstart&lt;/a&gt; page for more information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="/magellan"&gt;Back to: Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-installer/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=XFq4kvEAK0w:m67x2XDPmpw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=XFq4kvEAK0w:m67x2XDPmpw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=XFq4kvEAK0w:m67x2XDPmpw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=XFq4kvEAK0w:m67x2XDPmpw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-mvvm-light-toolkit</id>
        <title type="text">Magellan and the MVVM Light Toolkit</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-mvvm-light-toolkit" />
        <published>2009-11-13T07:13:39Z</published>
        <updated>2009-11-13T07:13:39Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://www.galasoft.ch/mvvm/getstarted/"&gt;MVVM Light Toolkit&lt;/a&gt; is an MVVM framework by WPF MVP &lt;a href="http://www.galasoft.ch/"&gt;Laurent Bugnion&lt;/a&gt;, the author of &lt;a href="http://www.galasoft.ch/SL2U/Default.aspx"&gt;Silverlight 2 Unleashed&lt;/a&gt;. It works well alongside Magellan and makes it easy to put behaviors behind views. The integration model with Magellan is quite similar to using the &lt;a href="/magellan-mvvm-toolkit"&gt;Microsoft MVVM toolkit&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;One difference is that the MVVM Light Toolkit typically uses resources to refer to the ViewModel, limiting the amount of code behind that is required. Since Magellan controllers typically create the model, this does need to change. &lt;/p&gt;

&lt;p&gt;As with using the Microsoft MVVM toolkit, we use the controller to create the ViewModel:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HomeController : Controller
{
    public ActionResult Main()
    {
        Model = new MainViewModel();
        return View();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;MVVM Light views typically use a locator for creating the view model - this is a problem because our controller above will be creating the VM, and Magellan is taking care of assigning it. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Window x:Class="MvvmLight1.MvvmView1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d"
    DataContext="{Binding Main, Source={StaticResource Locator}}"
    &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To keep Blend support, change the XAML to use &lt;code&gt;d:DataContext&lt;/code&gt; instead of &lt;code&gt;DataContext&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Window x:Class="MvvmLight1.MvvmView1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModel="clr-namespace:MvvmLight1.ViewModel" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    mc:Ignorable="d"
    d:DataContext="{x:Type ViewModel:MainViewModel}"
    &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-mvvm-light-toolkit/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=c-eKm_0-BOc:TTBIdccvbUk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=c-eKm_0-BOc:TTBIdccvbUk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=c-eKm_0-BOc:TTBIdccvbUk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=c-eKm_0-BOc:TTBIdccvbUk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-controllers</id>
        <title type="text">Magellan Controllers</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-controllers" />
        <published>2009-11-12T10:11:38Z</published>
        <updated>2009-11-12T10:11:38Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As an MVC framework, controllers are the most prominent object in Magellan. At their simplest, controllers are implemented as classes, and actions are implemented as methods on the class. Actions on a controller must be public methods, and must return &lt;code&gt;ActionResult&lt;/code&gt; objects. Here is an example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class CustomerController : Controller
{
    public ActionResult Index()
    {
        Model = Customers.GetAll();
        return View();
    }

    public ActionResult Show(int customerId) 
    {
        Model = Customers.Get(customerId);
        return View();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This page describes how controllers are executed. &lt;/p&gt;

&lt;h1&gt;Controller Factories&lt;/h1&gt;

&lt;p&gt;Navigation begins at the &lt;a href="/magellan-navigator"&gt;Navigator&lt;/a&gt;, either by using a &lt;a href="/magellan-commands"&gt;command&lt;/a&gt;, &lt;a href="/magellan-behaviors"&gt;behavior&lt;/a&gt; or calling it explicitly. The Navigator processes the request by resolving a controller from the controller factory, executing the request, and releasing the controller back to the factory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void Navigate(NavigationRequest request)
{
    Guard.ArgumentNotNull(request, "request");

    var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
    var controller = controllerFactory.CreateController(request, request.Controller);
    try
    {
        controller.Execute(request);
    }
    finally
    {
        controllerFactory.ReleaseController(controller);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The controller factory implements the &lt;code&gt;IControllerFactory&lt;/code&gt; interface, and provides two methods to control the management of controllers:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IControllerFactory
{
    IController CreateController(NavigationRequest request, string controllerName);
    void ReleaseController(IController controller);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The controller factory is set via the &lt;code&gt;ControllerBuilder.Current.SetControllerFactory&lt;/code&gt; method. See the topic on &lt;a href="/magellan-ioc"&gt;using an IOC container&lt;/a&gt; for an example on creating your own controller factory. &lt;/p&gt;

&lt;h1&gt;Controllers&lt;/h1&gt;

&lt;p&gt;The controllers returned by the controller factory must implement the &lt;code&gt;IController&lt;/code&gt; interface, which is quite simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public interface IController
{
    void Execute(NavigationRequest request);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;NavigationRequest&lt;/code&gt; passed to the controller contains information about the controller name, action name, and any parameters for the request. It is up to the controller to decide how to handle the request given this information. If the class/method convention used by Magellan isn't enough, your controller can use different mechanisms to prosecute the request. Magellan's navigator, behaviors, and commands can still be used. &lt;/p&gt;

&lt;p&gt;Controllers will usually derive from the &lt;code&gt;Controller&lt;/code&gt; base class. When this controller executes a request, it will work with an &lt;em&gt;action invoker&lt;/em&gt; to resolve the action, call any &lt;a href="/magellan-action-filters"&gt;action filters&lt;/a&gt;, execute the action, and evaluate the result.&lt;/p&gt;

&lt;p&gt;The Execute method on the Controller base class is quite simple:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void Execute(NavigationRequest request)
{
    Request = request;
    ActionInvoker.ExecuteAction(ControllerContext, request.Action, ModelBinders);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To make writing controllers easy, a number of helper methods exist for creating the action results, such as &lt;code&gt;View()&lt;/code&gt;, &lt;code&gt;Cancel()&lt;/code&gt; and &lt;code&gt;Redirect()&lt;/code&gt;. You can read more about them in the &lt;a href="/magellan-action-results"&gt;action results&lt;/a&gt; section.&lt;/p&gt;

&lt;h1&gt;Action Invoker&lt;/h1&gt;

&lt;p&gt;The action invoker is used by the controller to handle the details of executing the action. This allows you to continue to derive from the &lt;code&gt;Controller&lt;/code&gt; class while executing actions in a very different way. By default, the controller's &lt;code&gt;ActionInvoker&lt;/code&gt; property is set to the &lt;code&gt;DefaultActionInvoker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The default action invoker uses reflection to map the requests Action property to a method on the controller. It then performs the following steps: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Executes all pre-action filters&lt;/li&gt;
&lt;li&gt;Executes the action&lt;/li&gt;
&lt;li&gt;Executes all post-action filters&lt;/li&gt;
&lt;li&gt;Executes the action result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="/magellan-action-filters"&gt;Action filters&lt;/a&gt; provide a way for you to implement cross-cutting concerns on controllers, such as authorization, logging, state management, and other examples.&lt;/p&gt;

&lt;p&gt;When the action has been executed, it will return an &lt;a href="/magellan-action-results"&gt;Action Result&lt;/a&gt;. This is an important point - controllers do not show views directly, they simply return an object which is responsible for resolving and showing the view. This allows you handle the navigation request in a very different way without altering controllers. &lt;/p&gt;

&lt;h1&gt;Model Binders&lt;/h1&gt;

&lt;p&gt;One of the tasks the action invoker takes care of is mapping parameters from the current &lt;code&gt;NavigationRequest&lt;/code&gt; to arguments passed to the action method on the controller. Rather than putting this logic in the action invoker, it instead calls through to objects known as &lt;code&gt;Model Binders&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ModelBinders.Binders&lt;/code&gt; static property is a registry of active model binders, associated with a type. By default there is only one binder - a &lt;code&gt;DefaultModelBinder&lt;/code&gt; which uses type descriptors and casting to perform the conversion. If you wish to customize how request parameters are mapped to action method parameters, you can do so through implementing the &lt;code&gt;IModelBinder&lt;/code&gt; interface and registering it with the &lt;code&gt;ModelBinders.Binders&lt;/code&gt; collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/magellan-ioc"&gt;Using Magellan with an IOC container&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-action-results"&gt;Action Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-action-filters"&gt;Action Filters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-controllers/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=0GhGZSPH5Ko:kGagjGefQro:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=0GhGZSPH5Ko:kGagjGefQro:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=0GhGZSPH5Ko:kGagjGefQro:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=0GhGZSPH5Ko:kGagjGefQro:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-mvvm-toolkit</id>
        <title type="text">Magellan and the Microsoft MVVM Toolkit</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-mvvm-toolkit" />
        <published>2009-11-11T06:38:49Z</published>
        <updated>2009-11-11T06:38:49Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="/magellan"&gt;Magellan&lt;/a&gt;&lt;/strong&gt;'s MVC framework is designed to handle navigation between views. However, the views themselves, and how they are implemented, is outside of Magellan's concern. Views can be simple XAML pages, or they can be driven by an MVVM or MVP pattern, or any other way you might like. &lt;/p&gt;

&lt;p&gt;Microsoft provide a Visual Studio project template known as the &lt;a href="http://wpf.codeplex.com/wikipage?title=WPF%20Model-View-ViewModel%20Toolkit&amp;amp;referringTitle=Home"&gt;MVVM Toolkit&lt;/a&gt;, which makes it easy to get started using the MVVM pattern. &lt;/p&gt;

&lt;p&gt;To use Magellan with the MVVM toolkit, you can set up a new MVVM project using the MVVM project template. Then configure it the same way as described in the &lt;a href="/magellan-quickstart"&gt;Magellan quickstart&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;By default with the MVVM toolkit, you typically create the ViewModel and View and assign them yourself, as shown in the project template:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Views.MainView view = new Views.MainView();
view.DataContext = new ViewModels.MainViewModel();
view.Show();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead, with Magellan, you can assign the controller's Model property to you ViewModel:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class HomeController : Controller
{
    public ActionResult Main()
    {
        Model = new MainViewModel();
        return View();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;a href="/magellan-view-engines"&gt;view engines&lt;/a&gt; will create the page or Window, and set the &lt;code&gt;DataContext&lt;/code&gt; to the Model for you. It will then navigate to the page or show the Window. &lt;/p&gt;

&lt;p&gt;Your ViewModels can make use of commands, event managers, data binding, and all the other common MVVM patterns. MVVM would typically handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local interaction with the view&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Control state, such as whether a button should be enabled based on data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Magellan would be used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigating to another page or window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good way to think about this is to think in terms of the web. On the web, JavaScript is typically the "view model" - it handles the logic for a particular page. The server processes requests for many pages and navigation between pages - that's the job of Magellan. &lt;/p&gt;

&lt;p&gt;There is also a &lt;a href="/magellan-commands"&gt;NavigateCommand&lt;/a&gt; that can be used in ViewModels, instead of the need to use a &lt;code&gt;DelegateCommand&lt;/code&gt;/&lt;code&gt;RelayCommand&lt;/code&gt; for common navigation events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-mvvm-toolkit/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=D5XUNoGtUjE:LYhIJ2WRzQI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=D5XUNoGtUjE:LYhIJ2WRzQI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=D5XUNoGtUjE:LYhIJ2WRzQI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=D5XUNoGtUjE:LYhIJ2WRzQI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-composite-wpf</id>
        <title type="text">Magellan and Composite WPF</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-composite-wpf" />
        <published>2009-11-10T13:07:43Z</published>
        <updated>2009-11-10T13:07:43Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magellan was designed to work with &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;Composite WPF&lt;/a&gt; from day one.&lt;/strong&gt; Composite WPF provides support for multiple modules, loosely coupled pub/sub eventing, and regions for sub-dividing zones in the UI. However, Composite WPF does not enforce any particular UI pattern - MVVM, MVP and MVC could all work. &lt;/p&gt;

&lt;p&gt;Magellan and Composite WPF can work well together to create a composite navigation-oriented application using the MVC pattern. Here are some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composite WPF modules could contain views and controllers &lt;/li&gt;
&lt;li&gt;Composite WPF events could be used for navigation - i.e., a Navigate event that could be raised by different modules and services&lt;/li&gt;
&lt;li&gt;Instead of pages, Magellan view results could return UserControls that are added to regions&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Region Support&lt;/h1&gt;

&lt;p&gt;For region support, &lt;strong&gt;Magellan.Composite.dll&lt;/strong&gt; contains some extensions that can be used. A controller may look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class ShellController: Controller 
{
    public ActionResult Explorer()
    {
        return View().InRegion("LeftRegion");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On application startup, the view can be navigated to via:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Navigator.Primary.Navigate("Shell", "Explorer");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Lastly, an additional &lt;a href="/magellan-view-engines"&gt;Region View Engine&lt;/a&gt; needs to be registered. As discussed in the &lt;a href="/magellan-ioc"&gt;IOC&lt;/a&gt; topic, you can also use a custom view activator to control how views are instantiated, if you want to use IOC. In this case we'll use the Microsoft common ServiceLocator:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new PageViewEngine(new ServiceLocatorViewActivator()));
ViewEngines.Engines.Add(new WindowViewEngine(new ServiceLocatorViewActivator()));
ViewEngines.Engines.Add(new RegionViewEngine(new ServiceLocatorViewActivator()));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When the &lt;code&gt;InRegion&lt;/code&gt; extension method is used, and the view class derives from &lt;code&gt;UIElement&lt;/code&gt;, the region view engine will use the service locator to resolve the default &lt;code&gt;RegionManager&lt;/code&gt;, and then add the view to the region. &lt;/p&gt;

&lt;h1&gt;Controller Factory&lt;/h1&gt;

&lt;p&gt;There is also a new controller factory that can be used with the Common Service Locator. It will automatically back onto &lt;code&gt;ServiceLocator.Current&lt;/code&gt; to resolve controllers, so you just have to register them in the container:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;See also:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/magellan-ioc"&gt;Using Magellan with an IOC Container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-mvvm-toolkit"&gt;Using Magellan with Microsoft MVVM Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-composite-wpf/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=ODBSmCGDOaI:7ArHvOOx0XY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=ODBSmCGDOaI:7ArHvOOx0XY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=ODBSmCGDOaI:7ArHvOOx0XY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=ODBSmCGDOaI:7ArHvOOx0XY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-ioc</id>
        <title type="text">Magellan and IOC/DI Containers</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-ioc" />
        <published>2009-11-09T11:37:38Z</published>
        <updated>2009-11-09T11:37:38Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Magellan was designed to work without an &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control or Dependency Injection&lt;/a&gt; container, to keep it simple and accessible. However, as applications become more complicated, modern WPF applications can benefit immensely from IOC containers.&lt;/p&gt;

&lt;p&gt;Magellan's extensibility points make using a container easy. Magellan resolves and instantiates two main types of objects - controllers and views. The out of the box implementation uses conventions, but they can be overridden.&lt;/p&gt;

&lt;p&gt;To take control of resolving &lt;a href="/magellan-controllers"&gt;controllers&lt;/a&gt;, implement the &lt;code&gt;IControllerFactory&lt;/code&gt; interface. Here is an example using &lt;a href="http://ninject.org"&gt;Ninject&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class NinjectControllerFactory : IControllerFactory
{
    private readonly IKernel _container;

    public NinjectControllerFactory(IKernel container)
    {
        _container = container;
    }

    public IController CreateController(NavigationRequest request, string controllerName)
    {
        return _container.Get&amp;lt;IController&amp;gt;(controllerName);
    }

    public void ReleaseController(IController controller)
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then assign it as the default controller factory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var container = new StandardKernel();
container.Bind&amp;lt;IController&amp;gt;().To&amp;lt;HomeController&amp;gt;().Named("Home");
container.Bind&amp;lt;IController&amp;gt;().To&amp;lt;SettingsController&amp;gt;().Named("Settings");
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(container));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When a navigation request is processed, the &lt;a href="/magellan-navigator"&gt;Navigator&lt;/a&gt; will consult the &lt;code&gt;ControllerBuilder.Current&lt;/code&gt; for the controller factory. It will use this to ask the factory for a controller, then execute the controller. The &lt;code&gt;ReleaseController&lt;/code&gt; method will be called as soon as the navigation request has completed. &lt;/p&gt;

&lt;p&gt;Typically, each navigation will create a new controller - if you want to use the same controller, you could have your controller factory recycle the objects, or make them singletons.&lt;/p&gt;

&lt;p&gt;The second object that Magellan creates is views. This is done through the IViewActivator implementation. The default implementation looks for a public, parameterless constructor. &lt;/p&gt;

&lt;p&gt;Again, let's use Ninject to control view instantiation.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class NinjectViewActivator : IViewActivator
{
    private readonly IKernel _container;

    public NinjectViewActivator(IKernel container)
    {
        _container = container;
    }

    public object Instantiate(Type viewType)
    {
        return _container.Get(viewType);        
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We then need to tell the &lt;a href="/magellan-view-engines"&gt;view engines&lt;/a&gt; that it is available. Since the view engines are automatically registered, we need to manually re-register them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var activator = new NinjectViewActivator(container);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new PageViewEngine(activator));
ViewEngines.Engines.Add(new WindowViewEngine(activator));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you are using &lt;a href="/magellan-composite-wpf"&gt;Magellan with Composite WPF&lt;/a&gt;, you will also need to register the region view engine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ViewEngines.Engines.Add(new RegionViewEngine(activator));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-ioc/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=iN1qQEfUk_w:AlmH_6bnFLc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=iN1qQEfUk_w:AlmH_6bnFLc:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=iN1qQEfUk_w:AlmH_6bnFLc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=iN1qQEfUk_w:AlmH_6bnFLc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/magellan-quickstart</id>
        <title type="text">Magellan Quickstart</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/magellan-quickstart" />
        <published>2009-11-14T14:13:41Z</published>
        <updated>2009-11-14T14:13:41Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This guide will walk you through getting started with &lt;a href="/magellan"&gt;Magellan&lt;/a&gt;. You will need a copy of Visual Studio 2008 with Service Pack 1. &lt;/p&gt;

&lt;h1&gt;Project Setup&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://get.paulstovell.com/Magellan"&gt;Download the Magellan library&lt;/a&gt;. Unzip it to a known location.&lt;/li&gt;
&lt;li&gt;Create a new WPF Application project using Visual Studio 2008. &lt;/li&gt;
&lt;li&gt;Add references to &lt;strong&gt;Magellan.dll&lt;/strong&gt; and &lt;strong&gt;System.Windows.Interactivity.dll&lt;/strong&gt; from the ZIP file that you downloaded.&lt;/li&gt;
&lt;li&gt;Create the following folder structure:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="/get/magellan/magellan-empty-project.png" alt="A new VS project, ready for Magellan" /&gt;&lt;/p&gt;

&lt;h1&gt;Create a model&lt;/h1&gt;

&lt;p&gt;In the &lt;strong&gt;Views/Home&lt;/strong&gt; folder, add a class named AddModel. This will represent the view model of an addition action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class AddModel
{
    public int A { get; set; }
    public int B { get; set; }
    public int Result { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Create a controller&lt;/h1&gt;

&lt;p&gt;Create a new class in the &lt;strong&gt;Controllers&lt;/strong&gt; folder named &lt;strong&gt;HomeController&lt;/strong&gt;. It will contain two actions - &lt;strong&gt;Index&lt;/strong&gt;, which will be the input page, and &lt;strong&gt;Add&lt;/strong&gt;, which will show the results:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;using Magellan.Framework;

namespace MagellanHelloWorld.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Add(int a, int b)
        {
            Model = new AddModel
            {
                A = a,
                B = b,
                Result = a + b
            };
            return View();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now wire up the controller in &lt;strong&gt;App.xaml.cs&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;using System.Windows;
using Magellan.Framework;
using MagellanHelloWorld.Controllers;

namespace MagellanHelloWorld
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            var controllerFactory = new ControllerFactory();
            controllerFactory.Register("Home", () =&amp;gt; new HomeController());
            ControllerBuilder.Current.SetControllerFactory(controllerFactory);

            base.OnStartup(e);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Set up the shell&lt;/h1&gt;

&lt;p&gt;In &lt;strong&gt;Window1.xaml&lt;/strong&gt;, add a &lt;strong&gt;Frame&lt;/strong&gt; element to the content:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Window 
    x:Class="MagellanHelloWorld.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    &amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;Frame Name="mainFrame" /&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the Window1 constructor, navigate the mainFrame to the &lt;strong&gt;Index&lt;/strong&gt; action on your controller.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;using System.Windows;
using Magellan;

namespace MagellanHelloWorld
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            Navigator.For(mainFrame).Navigate("Home", "Index");
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Create the views&lt;/h1&gt;

&lt;p&gt;In the &lt;strong&gt;Views/Home&lt;/strong&gt; folder, create two new &lt;strong&gt;Page&lt;/strong&gt; files: &lt;strong&gt;Index.xaml&lt;/strong&gt; and &lt;strong&gt;Add.xaml&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Index.xaml&lt;/strong&gt; will be used to capture the inputs, and send them to the &lt;strong&gt;Add&lt;/strong&gt; action on the controller. Notice how the &lt;strong&gt;Parameters&lt;/strong&gt; are defined as part of the &lt;a href="/magellan-behaviors"&gt;Navigation behavior&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Page 
    x:Class="MagellanHelloWorld.Views.Home.Index"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:magellan="http://xamlforge.com/magellan" 
    Title="Index"
    &amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBox Name="parameterA" /&amp;gt;
        &amp;lt;TextBlock Text="+" /&amp;gt;
        &amp;lt;TextBox Name="parameterB" /&amp;gt;

        &amp;lt;Button Content="Calculate"&amp;gt;
            &amp;lt;i:Interaction.Behaviors&amp;gt;
                &amp;lt;magellan:NavigateBehavior Controller="Home" Action="Add"&amp;gt;
                    &amp;lt;magellan:NavigateBehavior.Parameters&amp;gt;
                        &amp;lt;magellan:Parameter ParameterName="a" Value="{Binding ElementName=parameterA, Path=Text}" /&amp;gt;
                        &amp;lt;magellan:Parameter ParameterName="b" Value="{Binding ElementName=parameterB, Path=Text}" /&amp;gt;
                    &amp;lt;/magellan:NavigateBehavior.Parameters&amp;gt;
                &amp;lt;/magellan:NavigateBehavior&amp;gt;
            &amp;lt;/i:Interaction.Behaviors&amp;gt;
        &amp;lt;/Button&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/Page&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;strong&gt;Add.xaml&lt;/strong&gt; will show the output of the calculation. Note how it assumes the use of &lt;code&gt;DataContext&lt;/code&gt; in the bindings. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;Page 
    x:Class="MagellanHelloWorld.Views.Home.Add"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:magellan="http://xamlforge.com/magellan" 
    Title="Add"
    &amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;WrapPanel&amp;gt;
            &amp;lt;TextBlock Text="{Binding Path=A}" /&amp;gt;
            &amp;lt;TextBlock Text="+" /&amp;gt;
            &amp;lt;TextBlock Text="{Binding Path=B}" /&amp;gt;
            &amp;lt;TextBlock Text="=" /&amp;gt;
            &amp;lt;TextBlock Text="{Binding Path=Result}" /&amp;gt;
        &amp;lt;/WrapPanel&amp;gt;

        &amp;lt;Button Content="Try Again"&amp;gt;
            &amp;lt;i:Interaction.Behaviors&amp;gt;
                &amp;lt;magellan:NavigateBehavior Controller="Home" Action="Index" /&amp;gt;
            &amp;lt;/i:Interaction.Behaviors&amp;gt;
        &amp;lt;/Button&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/Page&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Magellan &lt;a href="/magellan-view-engines"&gt;view engine&lt;/a&gt; will take care of setting the &lt;code&gt;Page&lt;/code&gt;'s &lt;code&gt;DataContext&lt;/code&gt; to the &lt;code&gt;Model&lt;/code&gt; from the controller.&lt;/p&gt;

&lt;h1&gt;Done&lt;/h1&gt;

&lt;p&gt;That's all there is to it - just hit F5 and admire the results of your handywork! At this point you should be able to enter the values, and they will appear on the next page. Wasn't that easy? &lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/quickstart-index-page.PNG" alt="Index.xaml" /&gt;
&lt;img src="/get/magellan/quickstart-add-page.PNG" alt="Add.xaml" /&gt;&lt;/p&gt;

&lt;p&gt;Magellan took care of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Locating the controller&lt;/li&gt;
&lt;li&gt;Invoking the actions&lt;/li&gt;
&lt;li&gt;Mapping the strings from the text boxes to integer parameters on the action (using &lt;a href="/magellan-controllers"&gt;Model Binders&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Locating the view&lt;/li&gt;
&lt;li&gt;Connecting the model with the view&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Tests&lt;/h1&gt;

&lt;p&gt;Of course, it wouldn't be complete without a test. Here's what the unit test for our &lt;strong&gt;Add&lt;/strong&gt; action might look like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Test]
public void AddTest()
{
    var controller = new HomeController();
    controller.Add(1, 4);
    var model = (AddModel)controller.Model;

    Assert.AreEqual(1, model.A);
    Assert.AreEqual(4, model.B);
    Assert.AreEqual(5, model.Result);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;What next?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="/magellan-ioc"&gt;Using Magellan with an IOC container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-composite-wpf"&gt;Using Magellan with Composite WPF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-mvvm-toolkit"&gt;Using Magellan with Microsoft MVVM Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-mvvm-light-toolkit"&gt;Using Magellan with MVVM Light Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/magellan-caliburn"&gt;Using Magellan with Caliburn and MVP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/magellan-quickstart/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=eDVjpkbAIgg:3RyN49X4Qds:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=eDVjpkbAIgg:3RyN49X4Qds:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=eDVjpkbAIgg:3RyN49X4Qds:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=eDVjpkbAIgg:3RyN49X4Qds:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/introducing-magellan</id>
        <title type="text">Magellan Introduction</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/introducing-magellan" />
        <published>2009-11-15T12:41:30Z</published>
        <updated>2009-11-15T12:41:30Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magellan&lt;/strong&gt; is a lightweight framework that makes it easy to build &lt;a href="/wpf-navigation"&gt;WPF navigation&lt;/a&gt; applications. It is inspired by the ASP.NET MVC framework. The main features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model-View-Controller support&lt;/li&gt;
&lt;li&gt;Action filters for cross-cutting concerns such as authorization and redirection&lt;/li&gt;
&lt;li&gt;Blend behaviors to make navigation easy&lt;/li&gt;
&lt;li&gt;Transitions between pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Magellan was drawn from a number of samples I had put together early this year and some work done on a client project. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://get.paulstovell.com/magellan"&gt;Download the library&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="http://get.paulstovell.com/magellan"&gt;Download the source code (with sample application)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source download includes an "iPhone" application for demonstrating the features.&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/iphone-sample.png" alt="The sample iPhone application" /&gt;&lt;/p&gt;

&lt;p&gt;We start with a simple project structure:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/project-structure.png" alt="A VS2008 project with a number of folders for controllers, models and views" /&gt;&lt;/p&gt;

&lt;p&gt;A controller implementation typically looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class PhoneController : Controller
{
    public ActionResult Group(Group group)
    {
        var contacts = _contactRepository.GetContacts(group);

        Model = new GroupViewModel(group.Name, contacts);
        return View();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Views are XAML Page objects, and can optionally have a model. Here's an example:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/view-models.png" alt="View models" /&gt;&lt;/p&gt;

&lt;p&gt;The idea is that upon navigation, a controller is created, the action is executed, and the view and view model are created. The view then becomes the focus of the frame. Put simply, the view and viewmodel are stateful, and the controller is stateless. &lt;/p&gt;

&lt;p&gt;Navigation between views (with nice transitions) can be done either programatically:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Navigator.For(Frame).NavigateWithTransition("Home", "Main", "ZoomOut");
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or through Blend behaviors:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/magellan/blend-navigate-behavior.PNG" alt="Blend Navigate behavior" /&gt;&lt;/p&gt;

&lt;p&gt;The framework supports the ASP.NET MVC concepts of Action Filters, Model Binders, View Engines and more - I'll cover them in a later post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Back to: &lt;a href="/magellan"&gt;Magellan Home&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/introducing-magellan/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=WRiMyg5rDMA:D-0S-3QuWIQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=WRiMyg5rDMA:D-0S-3QuWIQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=WRiMyg5rDMA:D-0S-3QuWIQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=WRiMyg5rDMA:D-0S-3QuWIQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/enforced-strings</id>
        <title type="text">Enforced Strings</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/enforced-strings" />
        <published>2009-10-09T13:02:24Z</published>
        <updated>2009-10-09T13:02:24Z</updated>
        
    <content type="html">
        
        &lt;p&gt;Enterprise applications typically deal with many categories of strings. Human names, reference codes, SKU identifiers, email addresses - the list is huge. There are subtle rules that apply to many of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whitespace at the start and end of many strings should probably be ignored &lt;/li&gt;
&lt;li&gt;Human names probably shouldn't contain newlines, tab characters, the percentage symbol, or 27 dashes in a row&lt;/li&gt;
&lt;li&gt;For some strings, casing makes no difference when deciding equality, and sometimes it does&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's common to litter our code with these assumptions, which leads to inconsistency. Sometimes we assume that the UI will handle all of these issues, and the domain layer will simply use what it's given. &lt;/p&gt;

&lt;p&gt;Recently I have started experimenting with creating custom strings to encapsulate a lot of these subtle things. On my blog, when you browse to a URL like &lt;a href="/enforced-strings"&gt;/enforced-strings&lt;/a&gt;, instead of the page name being passed around as a string, it's passed as a PageName object. PageName supports implicit conversion operators, so it can be dealt with as a regular string too. Here is part of a unit test:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PageName expected = "hello-world";

// When cast to a PageName, each of these should be converted into the above
var logicallySameAsExpected = new string[] {
    "hello-world",
    "hello-worLD",
    " hello -world ",
    " hello$-world ",
    " hello $-world ",
    " hello-$-world ",
    " hello world ",
    " -   hello   world   - ",
    " -   HeLLo  WoRLD  - ",
    " -   HeLLo  %^@#@#*()[]WoRLD  - ",
    " -   HeLLo  %^@#@#*()[]WoRLD  - $%",
    "@# -   HeLLo  %^@#@#*()[]WoRLD  - $%"
};

foreach (var match in logicallySameAsExpected)
{
    var castMatch = (PageName) match;
    Assert.AreEqual(expected, castMatch);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The assumption I make with PageName is that while it may be instantiated with dirty input (a malformed URL, for example), I can probably infer what was meant. PageName is used throughout my domain model and even at the data access layer - in my case, I use a custom &lt;a href="http://svn.paulstovell.com/svn/PaulPad/Source/PaulPad.Web/Model/Mappings/UserTypes/PageNameUserType.cs"&gt;IUserType&lt;/a&gt; with NHibernate to treat strings from the database as page names.&lt;/p&gt;

&lt;p&gt;To build your own enforced strings, here are the key things to consider doing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a class to wrap a real string&lt;/li&gt;
&lt;li&gt;Make it immutable, and ideally sealed&lt;/li&gt;
&lt;li&gt;In the constructor, massage the input string&lt;/li&gt;
&lt;li&gt;Override all of the equality operators, GetHashCode, etc., and implement IEquatable, and IComparable&lt;/li&gt;
&lt;li&gt;Override ToString (obviously)&lt;/li&gt;
&lt;li&gt;Add an implicit cast operator to automatically convert from your string to real strings and back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see an example of this in PaulPad - first I setup a &lt;a href="http://svn.paulstovell.com/svn/PaulPad/Source/PaulPad.Web/Model/Strings/EnforcedString.cs"&gt;base class with most of the overloads&lt;/a&gt;, then I &lt;a href="http://svn.paulstovell.com/svn/PaulPad/Source/PaulPad.Web/Model/Strings/PageName.cs"&gt;inherit from that to setup the specific string type&lt;/a&gt;. &lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/enforced-strings/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=1MSBTAQdKoE:_i0BT8CtAsA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=1MSBTAQdKoE:_i0BT8CtAsA:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=1MSBTAQdKoE:_i0BT8CtAsA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=1MSBTAQdKoE:_i0BT8CtAsA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/jquerypad</id>
        <title type="text">jQueryPad</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/jquerypad" />
        <published>2009-10-08T15:19:11Z</published>
        <updated>2009-10-08T15:19:11Z</updated>
        
    <content type="html">
        
        &lt;p&gt;jQueryPad is a fast JavaScript and HTML editor. Just start it, enter the HTML you want to work with, bash in your jQuery code, and hit F5 to see the results. Say goodbye to ALT+TAB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://get.paulstovell.com/jQueryPad/jQueryPad.zip"&gt;Download&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/jquerypad/jQueryPad.PNG" alt="jQueryPad screenshot" /&gt;&lt;/p&gt;

&lt;p&gt;jQueryPad is xcopy deployable. It's written in WPF and uses the Web Browser Control to embed Internet Explorer for testing the script. When you press F5, the HTML and JavaScript are combined into one file and rendered. The template also references jQuery, so the jQuery functions are available.&lt;/p&gt;

&lt;p&gt;If you want to use a different version of jQuery or reference other files, just replace the files in the Templates directory. &lt;/p&gt;

&lt;p&gt;Hope you find it useful - feature suggestions are welcome. &lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/jquerypad/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=IbXVuyOB7Lw:GT65myuDQ4E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=IbXVuyOB7Lw:GT65myuDQ4E:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=IbXVuyOB7Lw:GT65myuDQ4E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=IbXVuyOB7Lw:GT65myuDQ4E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/sheldon</id>
        <title type="text">Sheldon</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/sheldon" />
        <published>2009-10-07T12:16:53Z</published>
        <updated>2009-10-07T12:16:53Z</updated>
        
    <content type="html">
        
        &lt;p&gt;&lt;strong&gt;Sheldon&lt;/strong&gt; is a WPF command line control, and code to integrate it with IronPython. It's designed as a sample that demonstrates how a WPF application might be made scriptable:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/sheldon/Sheldon-Window-Control.png" alt="A screenshot of Sheldon" /&gt;&lt;/p&gt;

&lt;p&gt;This sample was created to pitch an idea to a client about enabling a macro system in their application. Users might be able to make use of functions like &lt;code&gt;OpenAccount("ACME")&lt;/code&gt;, &lt;code&gt;ExecuteJob("SalesForecast2009")&lt;/code&gt;, and so on. Using the Command Pattern, commands could be written to an Output window in the application while the user uses the UI - that could be used as a learning tool for learning the command line. &lt;/p&gt;

&lt;p&gt;The demo application shows how object models can be shared between your application and scripting environment. In C#, I set up an AutomationContext, which is made available to IronPython:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class AutomationContext
{
    public ApplicationDefinition Application { get; set; }
    public IScriptingContext ScriptingContext { get; set; }

    public void Exit()
    {
        Environment.Exit(0);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then in IronPython, I create a friendly "API" that users can consume:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;def GetWindow(name):
    return automation_context.Application.MainWindow
def Clear():
    automation_context.ScriptingContext.Clear()
def Exit():
    automation_context.Exit()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;ScriptingContext&lt;/code&gt; is an object that manages the execution and rendering of scripts, which the command line control can hook into. Multiple controls can talk to a single scripting context - here's a custom shell (I simply overrode the style and control template of the Shell control):&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/sheldon/Sheldon-Custom-Shell.PNG" alt="A custom shell style and template" /&gt;&lt;/p&gt;

&lt;p&gt;You can download the code here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ZIP: &lt;strong&gt;&lt;a href="http://get.paulstovell.com/Samples/Sheldon.zip"&gt;Sheldon.zip&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SVN: &lt;a href="http://svn.paulstovell.com/svn/Samples/Sheldon/"&gt;/svn/Samples/Sheldon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

        &lt;img src="http://www.paulstovell.com/sheldon/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=JduPJXCS4as:M_p-B2j_sjM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=JduPJXCS4as:M_p-B2j_sjM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=JduPJXCS4as:M_p-B2j_sjM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=JduPJXCS4as:M_p-B2j_sjM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/editable-collection-adapter</id>
        <title type="text">Editable Collection Adapter for WPF</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/editable-collection-adapter" />
        <published>2009-10-02T07:15:06Z</published>
        <updated>2009-10-02T07:15:06Z</updated>
        
    <content type="html">
        
        &lt;p&gt;The screenshot below is of a sample WPF application that deals with editing a collection of items:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/editable-collection-adapter/editable-collection.PNG" alt="The editable collection" /&gt;&lt;/p&gt;

&lt;p&gt;A few features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can make a batch of changes to the screen and hit "Save". &lt;/li&gt;
&lt;li&gt;If you deleted items, you can click "Show deleted items" to make them visible again, then click Undo to rollback the deletion&lt;/li&gt;
&lt;li&gt;The list on the left is bound to the same collection as the list on the right - the changes aren't written to the source until you click Save&lt;/li&gt;
&lt;li&gt;If you change an item, it highlights in bold&lt;/li&gt;
&lt;li&gt;If you change an item, you can undo the changes via the Undo button&lt;/li&gt;
&lt;li&gt;If you add items to the original collection, they will appear on screen (the Remote Update button)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The object representing an individual row is just a simple POCO object with &lt;code&gt;INotifyPropertyChanged&lt;/code&gt; support - it has no &lt;code&gt;HasChanges&lt;/code&gt; property or similar. Likewise, the collection is just an &lt;code&gt;ObservableCollection&amp;lt;T&amp;gt;&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This is all implemented with a mix of &lt;a href="/bindable-linq"&gt;BindableLINQ&lt;/a&gt; and the &lt;a href="/editable-object-adapter"&gt;Editable Object Adapter&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://get.paulstovell.com/Samples/WPF%20EditableCollection.zip"&gt;Download&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note: This sample uses the Xceed WPF DataGrid control. If you have a license, you can use your license key when running the sample (just set it in App.xaml.cs). Alternatively, you can download a &lt;a href="http://xceed.com/pages/TopMenu/Downloads/Trials.aspx?Lang=EN-CA"&gt;45 day trial from the Xceed website&lt;/a&gt;.&lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/editable-collection-adapter/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=riXtq35Wdfs:A1-7rQCSNto:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=riXtq35Wdfs:A1-7rQCSNto:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=riXtq35Wdfs:A1-7rQCSNto:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=riXtq35Wdfs:A1-7rQCSNto:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

    <entry>
        <id>http://www.paulstovell.com/wpf-delaybinding</id>
        <title type="text">DelayBinding: a custom WPF Binding</title>
        <author><name>Paul Stovell</name></author>
        <link rel="alternate" href="http://www.paulstovell.com/wpf-delaybinding" />
        <published>2009-10-02T01:58:18Z</published>
        <updated>2009-10-02T01:58:18Z</updated>
        
    <content type="html">
        
        &lt;p&gt;When you use the Outlook 2007 search, Vista's start search, or the Search bar in Explorer, there's often a short delay between when you press a key, and when the search begins. &lt;/p&gt;

&lt;p&gt;In WPF, we could simulate this through a series of event handlers, timers and code-behind directly on controls, but we usually want to be able to use this alongside WPF's data binding capabilities. To use WPF data binding in a delayed fashion, I created a simple &lt;a href="http://joshsmithonwpf.wordpress.com/2007/05/25/a-review-of-markup-extensions/"&gt;markup extension&lt;/a&gt; which creates a binding and manages the timer delay between commits. &lt;/p&gt;

&lt;p&gt;Here's how you can use it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;TextBox Text="{z:DelayBinding Path=SearchText}" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You can also set an explicit delay. By default, it uses 0.5 seconds, which felt consistent with Outlook, though I didn't spend that much time working out exactly how long Outlook waits. I did look to see if there was a &lt;strong&gt;SystemParameters&lt;/strong&gt; class for something like "SearchDelay", but couldn't find one. Suggestions for a better default are welcome. &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;TextBox Text="{z:DelayBinding Path=SearchText, Delay='00:00:01'}" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead of creating a new type of Binding, I'm using the standard WPF Binding, but setting the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger.aspx"&gt;UpdateSourceTrigger&lt;/a&gt; to Explicit. As the text changes, the timer is reset, and when it ticks the value is pushed to the source. &lt;/p&gt;

&lt;p&gt;&lt;img src="/get/delay-binding/delay-binding-before.png" alt="Delay binding - as the user types, the results do not change" /&gt;&lt;/p&gt;

&lt;p&gt;After the short delay:&lt;/p&gt;

&lt;p&gt;&lt;img src="/get/delay-binding/delay-binding-after.png" alt="...but after the short delay, the results change" /&gt;&lt;/p&gt;

&lt;p&gt;First, the code to the markup extension (XML-doc comments removed):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[MarkupExtensionReturnType(typeof(object))]
public class DelayBindingExtension : MarkupExtension
{
    public DelayBindingExtension()
    {
        Delay = TimeSpan.FromSeconds(0.5);
    }

    public DelayBindingExtension(PropertyPath path) 
        : this()
    {
        Path = path;
    }

    public IValueConverter Converter { get; set; }
    public object ConverterParamter { get; set; }
    public string ElementName { get; set; }
    public RelativeSource RelativeSource { get; set; }
    public object Source { get; set; }
    public bool ValidatesOnDataErrors { get; set; }
    public bool ValidatesOnExceptions { get; set; }
    public TimeSpan Delay { get; set; }
    [ConstructorArgument("path")]
    public PropertyPath Path { get; set; }
    [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))]
    public CultureInfo ConverterCulture { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideValueTarget;
        if (valueProvider != null)
        {
            var bindingTarget = valueProvider.TargetObject as DependencyObject;
            var bindingProperty = valueProvider.TargetProperty as DependencyProperty;
            if (bindingProperty == null || bindingTarget == null)
            {
                throw new NotSupportedException(string.Format(
                    "The property '{0}' on target '{1}' is not valid for a DelayBinding. The DelayBinding target must be a DependencyObject, "
                    + "and the target property must be a DependencyProperty.", 
                    valueProvider.TargetProperty, 
                    valueProvider.TargetObject));
            }

            var binding = new Binding();
            binding.Path = Path;
            binding.Converter = Converter;
            binding.ConverterCulture = ConverterCulture;
            binding.ConverterParameter = ConverterParamter;
            if (ElementName != null) binding.ElementName = ElementName;
            if (RelativeSource != null) binding.RelativeSource = RelativeSource;
            if (Source != null) binding.Source = Source;
            binding.ValidatesOnDataErrors = ValidatesOnDataErrors;
            binding.ValidatesOnExceptions = ValidatesOnExceptions;

            return DelayBinding.SetBinding(bindingTarget, bindingProperty, Delay, binding);
        }
        return null;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the &lt;strong&gt;DelayBinding&lt;/strong&gt; class, which as you can see above is being instantiated by the &lt;strong&gt;DelayBindingExtension.&lt;/strong&gt; You could also create it manually in code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class DelayBinding
{
    private readonly BindingExpressionBase _bindingExpression;
    private readonly DispatcherTimer _timer;

    protected DelayBinding(BindingExpressionBase bindingExpression, DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay)
    {
        _bindingExpression = bindingExpression;

        // Subscribe to notifications for when the target property changes. This event handler will be 
        // invoked when the user types, clicks, or anything else which changes the target property
        var descriptor = DependencyPropertyDescriptor.FromProperty(bindingTargetProperty, bindingTarget.GetType());
        descriptor.AddValueChanged(bindingTarget, BindingTarget_TargetPropertyChanged);

        // Add support so that the Enter key causes an immediate commit
        var frameworkElement = bindingTarget as FrameworkElement;
        if (frameworkElement != null)
        {
            frameworkElement.KeyUp += BindingTarget_KeyUp;
        }

        // Setup the timer, but it won't be started until changes are detected
        _timer = new DispatcherTimer();
        _timer.Tick += Timer_Tick;
        _timer.Interval = delay;
    }

    private void BindingTarget_KeyUp(object sender, KeyEventArgs e)
    {
        _timer.Stop();
        if (e.Key == Key.Enter) _bindingExpression.UpdateSource();
    }

    private void BindingTarget_TargetPropertyChanged(object sender, EventArgs e)
    {
        _timer.Stop();
        _timer.Start();
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        _timer.Stop();
        _bindingExpression.UpdateSource();
    }

    public static object SetBinding(DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay, Binding binding)
    {
        // Override some specific settings to enable the behavior of delay binding
        binding.Mode = BindingMode.TwoWay;
        binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;

        // Apply and evaluate the binding
        var bindingExpression = BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding);

        // Setup the delay timer around the binding. This object will live as long as the target element lives, since it subscribes to the changing event, 
        // and will be garbage collected as soon as the element isn't required (e.g., when it's Window closes) and the timer has stopped.
        new DelayBinding(bindingExpression, bindingTarget, bindingTargetProperty, delay);

        // Return the current value of the binding (since it will have been evaluated because of the binding above)
        return bindingTarget.GetValue(bindingTargetProperty);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I imagine this would be useful for Silverlight, but since Silverlight does not support custom &lt;strong&gt;MarkupExtensions&lt;/strong&gt;, and since Silverlight Binding's can't have an UpdateSourceTrigger (to set it to Explicit), I expect you would end up creating it through an attached dependency property and triggering the binding to push manually. Let me know if you write one. &lt;/p&gt;

        &lt;img src="http://www.paulstovell.com/wpf-delaybinding/via-feed" /&gt;
        
        &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=Wr7nORQ8KKw:9xtD2IziQVM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=Wr7nORQ8KKw:9xtD2IziQVM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/paulstovell?a=Wr7nORQ8KKw:9xtD2IziQVM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/paulstovell?i=Wr7nORQ8KKw:9xtD2IziQVM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</content></entry>

</feed>
