<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Christopher Bennage : Caliburn, WPF</title><link>http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/WPF/default.aspx</link><description>Tags: Caliburn, WPF</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>1 Simple Step for Commanding in Silverlight</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2010/03/03/1-simple-step-for-commanding-in-silverlight.aspx</link><pubDate>Wed, 03 Mar 2010 16:24:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:55619</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>3</slash:comments><description>&lt;p&gt;Silverlight 4 is now supporting the commanding that we’ve come to love from WPF. Commanding was a foundational feature for MVVM. It’s what enabled us to bind to methods on our view models.&lt;/p&gt;  &lt;p&gt;John Papa has an excellent introductory post on &lt;a href="http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight"&gt;using commands in Silverlight 4&lt;/a&gt;. This pattern is called the DelegatingCommand pattern (or sometimes RelayingCommand). &lt;/p&gt;  &lt;p&gt;I’d like to show you the &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; way of handling this. I’m going to steal John’s viewmodel from the aforementioned post (and hope he doesn’t sue).&lt;/p&gt;  &lt;p&gt;The viewmodel presents a collection of all products and a filtered collection of products. You can modify the filter by calling LoadProducts().&lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class ProductViewModel
{
    public ProductViewModel()
    {
        Products = new ObservableCollection&amp;lt;Product&amp;gt;();

        AllProducts = new ObservableCollection&amp;lt;Product&amp;gt;
                          {
                              new Product {ProductId = 1, ProductName = &amp;quot;Apple&amp;quot;},
                              new Product {ProductId = 2, ProductName = &amp;quot;Orange&amp;quot;},
                              new Product {ProductId = 3, ProductName = &amp;quot;Banana&amp;quot;},
                              new Product {ProductId = 4, ProductName = &amp;quot;Pear&amp;quot;},
                              new Product {ProductId = 5, ProductName = &amp;quot;Grape&amp;quot;},
                              new Product {ProductId = 6, ProductName = &amp;quot;Grapefruit&amp;quot;},
                              new Product {ProductId = 7, ProductName = &amp;quot;Strawberry&amp;quot;},
                              new Product {ProductId = 8, ProductName = &amp;quot;Melon&amp;quot;},
                              new Product {ProductId = 9, ProductName = &amp;quot;Guava&amp;quot;},
                              new Product {ProductId = 10, ProductName = &amp;quot;Kiwi&amp;quot;},
                              new Product {ProductId = 11, ProductName = &amp;quot;Pineapple&amp;quot;},
                              new Product {ProductId = 12, ProductName = &amp;quot;Mango&amp;quot;}
                          };
    }

    public ObservableCollection&amp;lt;Product&amp;gt; AllProducts { get; set; }

    public ObservableCollection&amp;lt;Product&amp;gt; Products { get; set; }

    public void LoadProducts(string filter)
    {
        Products.Clear();
        var query = from p in AllProducts
                    where p.ProductName.ToLower().StartsWith(filter.ToLower())
                    select p;
        foreach (var item in query)
        {
            Products.Add(item);
        }
    }

    public bool CanLoadProducts
    {
        get { return true; }
    }
}&lt;/pre&gt;

&lt;p&gt;Let me point out a few notable differences between John’s original and my version of the viewmodel.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There is no ICommand property. &lt;/li&gt;

  &lt;li&gt;CanLoadProducts is a property on my model, it was a method on the original &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The snippet from the corresponding view would look like this:&lt;/p&gt;

&lt;pre class="xml:nogutter:nocontrols" name="code"&gt;&amp;lt;StackPanel&amp;gt;
    &amp;lt;TextBox x:Name=&amp;quot;filter&amp;quot; /&amp;gt;
    &amp;lt;Button x:Name=&amp;quot;LoadProducts&amp;quot; Content=&amp;quot;Load&amp;quot; /&amp;gt;
&amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;

&lt;h3&gt;The Explanation&lt;/h3&gt;

&lt;p&gt;It’s &lt;em&gt;binding by convention&lt;/em&gt;, and it is a new feature of Caliburn added after the 1.1 release&lt;sup&gt;&lt;a id="fn1" title="see footnote"&gt;[1]&lt;/a&gt;&lt;/sup&gt;. So you’ll need to get the &lt;a href="http://caliburn.codeplex.com/SourceControl/list/changesets"&gt;trunk&lt;/a&gt; to do this. &lt;/p&gt;

&lt;p&gt;When you have a button named LoadProducts, Caliburn will look for a method on your viewmodel named LoadProducts and automagically handle the binding for you. In addition, it will check for either a method or property (as in this example) named CanLoadProducts that it will use to toggle the enable/disabled for the button. Also, since we have a parameter named “filter” on LoadProducts, Caliburn will check to see if there is an element in the view name “filter” and pull the value from that.&lt;/p&gt;

&lt;p&gt;There’s a great deal more that you can do with conventions (and you can even plug in your own conventions). &lt;/p&gt;

&lt;p&gt;This also works for Silverlight 3 and WPF. &lt;/p&gt;

&lt;p&gt;You can also see an example of this in &lt;a title="can I get a book?" href="http://github.com/ayende/Alexandria"&gt;Ayende’s sample app Alexandria&lt;/a&gt;.&lt;/p&gt;

&lt;div id="footnote"&gt;
  &lt;ol&gt;
    &lt;li id="1"&gt;&lt;em&gt;&lt;font size="2"&gt;Actually, you can do some of this in 1.0, but it is easier and much richer in the trunk. Ping &lt;/font&gt;&lt;a href="http://caliburn.codeplex.com/Thread/List.aspx"&gt;&lt;font size="2"&gt;the forums&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt; if you have a need to use it in 1.x.&lt;/font&gt; &lt;/em&gt;&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55619" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/mvvm/default.aspx">mvvm</category></item><item><title>Things I’d Like To Present</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2010/01/08/things-i-d-like-to-present.aspx</link><pubDate>Fri, 08 Jan 2010 11:32:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:54940</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;In case you are not familiar with &lt;a href="http://visitmix.com/" target="_blank"&gt;MIX&lt;/a&gt;, it is a conference from Microsoft focusing on the collaboration of design and development. Admittedly, the sessions tend to favor the developer, but there is always excellent design and UX content.&lt;/p&gt;  &lt;p&gt;&lt;a title="voting for MIX sessions" href="http://visitmix.com/opencallvote/?query=Christopher%20Bennage" target="_blank"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="Mix10_Vote_grn_240" border="0" alt="Mix10_Vote_grn_240" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/Mix10_5F00_Vote_5F00_grn_5F00_240_5F00_44742D31.jpg" width="184" height="244" /&gt;&lt;/a&gt; There was an open call for presentations this year and the community gets to choose which of the proposals will be selected. There are a number of &lt;a href="http://visitmix.com/opencallvote/" target="_blank"&gt;excellent proposals&lt;/a&gt; and I encourage you to go check out the list and vote for the sessions that you are genuinely interested in. (Even if you won’t be attending, the sessions will be broadcast.)&lt;/p&gt;  &lt;p&gt;Here are some sessions that I proposed for MIX10:&lt;/p&gt;  &lt;h3&gt;Cross Compiling Games for Silverlight &amp;amp; XNA&lt;/h3&gt;  &lt;p&gt;Our friend and Silverlight MVP, &lt;a href="http://blogs.silverarcade.com/silverlight-games-101/" target="_blank"&gt;Bill Reiss&lt;/a&gt;, has created an incredible library that enables you to cross compile XNA games for Silverlight. The library is called &lt;a title="a library for cross compiling XNA and Silverlight games" href="http://silversprite.codeplex.com/" target="_blank"&gt;SilverSprite&lt;/a&gt; and we feature it on Silver Arcade. (Wow, that’s a lot of ‘silvers’ in one paragraph.)&lt;/p&gt;  &lt;p&gt;In this session, we’d write a simple game for XNA (discussing some of the basic of game dev along the way) and then port the game over to Silverlight.&lt;/p&gt;  &lt;p&gt;This is an area where I wish I could spend more time. I love game development, but it’s always taking a back burner to other projects.   &lt;br /&gt;&lt;a title="Cross Compiling Games for Silverlight &amp;amp; XNA" href="http://visitmix.com/opencallvote/Entry?entryId=CROSSC046" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;LinqToSQL and EntityFramework Profilers: Case Study&lt;/h3&gt;  &lt;p&gt;If you aren’t already familiar with the UberProf suite of ORM profilers, you can read tales of the development on &lt;a href="http://ayende.com/Blog/category/561.aspx" target="_blank"&gt;Ayende’s blog&lt;/a&gt;. Rob and I built the UI side of the application, and we learned a lot in the process. I’d like to do a talk were we discuss the challenges of the project, how we solved them, and what we did wrong. &lt;/p&gt;  &lt;p&gt;Yes, NHProf will be included too. (I submitted a case study for it last year, and it didn’t get picked. I have to sneak it in).&amp;#160; &lt;/p&gt;  &lt;p&gt;A few interesting aspects: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;we built this using MVVM, but well before &lt;a href="http://www.codeplex.com/caliburn" target="_blank"&gt;Caliburn&lt;/a&gt; reached maturity. &lt;/li&gt;    &lt;li&gt;the four separate apps (NHProf, EFProf, L2SProf, HProf) all use a single code base.&lt;/li&gt;    &lt;li&gt;we’re about to port the project from WPF to Silverlight.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a title="LinqToSQL and EntityFramework Profilers: Case Study" href="http://visitmix.com/opencallvote/Entry?entryId=LINQTO047" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Silver Arcade: Case Study&lt;/h3&gt;  &lt;p&gt;This is a presentation that Rob and I have made a couple of times. Most recently at the Orlando .NET Users Group. We walk through the actual code for &lt;a href="http://www.silverarcade.com" target="_blank"&gt;Silver Arcade&lt;/a&gt; explaining the philosophy, design choices and mistakes we made along the way.&lt;/p&gt;  &lt;p&gt;For MIX, we would focus more design and UX choices, such as the separation of the behaviors from the views. However, we like to have a lot of audience interaction and tend to follow where ever the questions led (especially those leading questions that &lt;a href="http://scottdensmore.typepad.com/" target="_blank"&gt;Scott Densmore&lt;/a&gt; tends to ask). &lt;/p&gt;  &lt;p&gt;Silver Arcade is also interesting because&amp;#160; we deliberately used a number of newer hipper technologies; including Azure, ASP.NET MVC, jQuery, MEF, NHibernate and so on.   &lt;br /&gt; &lt;a title="case study of Silver Arcade" href="http://visitmix.com/opencallvote/Entry?entryId=SILVER048" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Thanks!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=54940" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Game+Development/default.aspx">Game Development</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/fun/default.aspx">fun</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/XNA/default.aspx">XNA</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/MVC/default.aspx">MVC</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Presentations/default.aspx">Presentations</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI+Patterns/default.aspx">UI Patterns</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/XAML/default.aspx">XAML</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/viewmodel/default.aspx">viewmodel</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/mvvm/default.aspx">mvvm</category></item><item><title>The Influence of MVC on my WPF</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2009/05/06/the-influence-of-mvc-on-my-wpf.aspx</link><pubDate>Wed, 06 May 2009 19:48:01 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:46528</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>9</slash:comments><description>&lt;p&gt;I was introduced to MVC as a pattern for Web development through &lt;a href="http://www.castleproject.org/monorail/" target="_blank"&gt;Castle MonoRail&lt;/a&gt;. From there I studied a bit of &lt;a href="http://rubyonrails.org/" target="_blank"&gt;Ruby on Rails&lt;/a&gt; (not enough) as well as the general philosophy of &lt;a href="http://www.37signals.com/" target="_blank"&gt;37signals&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;As I mentioned before, I thought I was moving away from Web development. However, the dive into ASP.NET MVC that &lt;a title="Silver Arcade, a free online gaming community" href="http://www.silverarcade.com/" target="_blank"&gt;Silver Arcade&lt;/a&gt; brought about has roped me back in.&lt;/p&gt;  &lt;p&gt;My work during the day (and some nights too) is still WPF though. I’ve discovered that MVC thinking has seeped into my WPF development.&lt;/p&gt;  &lt;h3&gt;Convention Over Configuration&lt;/h3&gt;  &lt;p&gt;A characteristic of most MVC frameworks is &lt;a href="http://en.wikipedia.org/wiki/Convention_over_Configuration" target="_blank"&gt;Convention Over Configuration&lt;/a&gt;. In short, it means that your “environment” makes assumptions about what you want and that you only need to be explicit about the exceptions.&lt;/p&gt;  &lt;p&gt;A practical example of this is the way that the View for an Action is inferred from the name of the Controller and Action. After creating your Action, you create a folder for the controller and and view that matches the name of the action. It just works. If you need to make exception, you can.&lt;/p&gt;  &lt;h3&gt;An Example in WPF&lt;/h3&gt;  &lt;p&gt;In our WPF development we employ a number of &lt;a title="I strongly dislike the term MVVM." href="http://msdn.microsoft.com/en-us/library/cc707862.aspx" target="_blank"&gt;Separated Presentation&lt;/a&gt; patterns. One of the more common patterns we use is MVP (in particular, the flavor of MVP implemented in &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt;, which is really Supervising Controller).&lt;/p&gt;  &lt;p&gt;Imagine a simple contact manager application. We can add new contacts, view a list of all contacts, and open individual contacts for viewing or editing. We can open as many individual contacts as we like.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="mvc" border="0" alt="mvc" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/mvc_5F00_313933F1.png" width="539" height="511" /&gt; &lt;/p&gt;  &lt;p&gt;Let’s say that there are buttons to open up the “Add New” view and “All Contacts” view. We can open an existing contact by double-clicking on them in the “All Contacts” view. &lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;margin:0px 8px 0px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="my imaginary solution" border="0" alt="my imaginary solution" align="left" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/56200930845PM_5F00_24D92471.png" width="271" height="341" /&gt;My solution setup for this imaginary (and highly contrived) application might look like this.&lt;/p&gt;  &lt;p&gt;ApplicationPresenter would be the root object of my UI. It would have an ObservableCollection of IPresenter that would be bound to a TabControl in Shell.xaml. Likewise, ApplicationPresenter will have a CurrentPresenter of IPresenter that will be bound to the SelectedItem on the TabControl. &lt;/p&gt;  &lt;p&gt;Shell.xaml is my only window in this example. All of the other views are user controls. I named it “shell” because I think of it as the outermost level of the views. Shell’s data context is set to ApplicationPresenter.&lt;/p&gt;  &lt;p&gt;I’m not going to dive too much deeper into this, because I want to get to my real point.&lt;/p&gt;  &lt;p&gt;My presenters don’t know anything about their views. It’s up to data binding to render each presenter with the correct view. This means that I need to create data templates for each of the presenters. Not such a big deal in a small application, but it can get tedious as the application grows.&lt;/p&gt;  &lt;p&gt;Hmmm… This structure is beginning to look a lot like an MVC app. Perhaps I can have it automatically infer my data templates for me?&lt;/p&gt;  &lt;h3&gt;Some Code&lt;/h3&gt;  &lt;p&gt;Yes we can. Here’s a &lt;em&gt;very naiveté&lt;/em&gt; bit of code that will do just that. It makes some big assumptions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;all of your presenters implement IPresenter &lt;/li&gt;    &lt;li&gt;all of your presenters are in a namespace containing “.Presenters” &lt;/li&gt;    &lt;li&gt;all of your views are in an analogous namespace containing in “.Views” &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Again, this is &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; production ready code, just my spike to prove the idea works. Please feel free to make suggestions.&lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public static class MvpConfiguration
{
    /// &amp;lt;summary&amp;gt;
    /// Creates a set of data templates pair to presenter classes based on naming conventions.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;If a data template is already present in the resources, then it is skipped.&amp;lt;/remarks&amp;gt;
    /// &amp;lt;param name=&amp;quot;resources&amp;quot;&amp;gt;The ResourceDictionary that the data templates for the views will be added to.&amp;lt;/param&amp;gt;
    public static void InferViewsFromPresenters(ResourceDictionary resources)
    {
        var lookup = MatchPresentersToViews();

        foreach (var pair in lookup)
        {
            var template = CreateDataTemplate(pair.Value, pair.Key);
            if (resources.Contains(template.DataTemplateKey)) continue;
            resources.Add(template.DataTemplateKey, template);
        }
    }

    private static Dictionary&amp;lt;Type, Type&amp;gt; MatchPresentersToViews()
    {
        var presenters = from type in Assembly.GetExecutingAssembly().GetTypes()
                         where typeof (IPresenter).IsAssignableFrom(type)
                         select type;

        var first = presenters.FirstOrDefault();
        if (first == null) throw new Exception(&amp;quot;I expected to find at least one presenters!&amp;quot;);

        string viewNamespace = first.Namespace
            .Replace(&amp;quot;.Presenters&amp;quot;, &amp;quot;.Views&amp;quot;);
        viewNamespace = viewNamespace.Substring(0, viewNamespace.IndexOf(&amp;quot;.Views&amp;quot;)+6);
        //yeah, that was hackish

        var views = from view in Assembly.GetExecutingAssembly().GetTypes()
                    where !string.IsNullOrEmpty(view.Namespace)
                          &amp;amp;&amp;amp; view.Namespace.StartsWith(viewNamespace)
                    select view;

        var table = new Dictionary&amp;lt;Type, Type&amp;gt;();

        foreach (var view in views)
        {
            var presenter = GetPresenterForView(view, presenters);
            if(presenter == null) continue;

            table.Add(presenter,view);
        }

        return table;
    }

    private static Type GetPresenterForView(Type type, IEnumerable&amp;lt;Type&amp;gt; presenters)
    {
        string name = type.Name.Replace(&amp;quot;View&amp;quot;, &amp;quot;Presenter&amp;quot;);
        var presenter =
            presenters.Where(p =&amp;gt; p.Name == name).FirstOrDefault();
        return presenter;
    }

    private static DataTemplate CreateDataTemplate(Type viewType, Type dataType)
    {
        var template = new DataTemplate(dataType);

        var factory = new FrameworkElementFactory(viewType);
        template.VisualTree = factory;
        return template;
    }
}&lt;/pre&gt;

&lt;p&gt;To use this, in your App.xaml.cs within OnStartup() add:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;MvpConfiguration.InferViewsFromPresenters(Resources);&lt;/pre&gt;

&lt;p&gt;What do you think? Am I totally nuts?&lt;/p&gt;

&lt;p&gt;Oh, and I should also point out that &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory.aspx" target="_blank"&gt;FrameworkElementFactory&lt;/a&gt; is actually deprecated. :-( Caveat emptor.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=46528" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/MVC/default.aspx">MVC</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/data+templates/default.aspx">data templates</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI+Patterns/default.aspx">UI Patterns</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category></item><item><title>Testing Bindings In WPF</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2009/02/19/testing-bindings-in-wpf.aspx</link><pubDate>Fri, 20 Feb 2009 03:56:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:44397</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>4</slash:comments><description>&lt;p&gt;I was inspired to get off my duff and blog today by &lt;a title="seriously, it&amp;#39;s voyeurism" href="http://twitter.com/shanselman/statuses/1228349932" target="_blank"&gt;a tweet from Scott Hanselman&lt;/a&gt;. I didn’t really dig into the context of his tweet, but it was about TDD and WPF. In case you haven’t figured it out, I’m a big fan of WPF and TDD. Luckily, I’ve had the opportunity to work on a number of varied WPF projects (most using TDD) over the last couple of years. One problem I experienced over and over was incorrect bindings in my Xaml (as I alluded to in &lt;a href="http://devlicious.com/blogs/christopher_bennage/archive/2009/01/19/ui-patterns-for-wpf.aspx" target="_blank"&gt;this post&lt;/a&gt;). Binding errors are silent. They sneak up on you ninja-like. If you are keeping an eye on your Output window you can catch them, but it is very easy for them to just slip by.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="Karate Lessons" border="0" alt="Karate Lessons" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/iStock_5F00_000004919619XSmall_5F00_18DE0A5B.jpg" width="240" height="159" /&gt;About two years ago, Rob and I were working on a student records application for the &lt;a href="http://music.fsu.edu/" target="_blank"&gt;FSU College of Music&lt;/a&gt;. The system handled the entire lifecycle of a student, from application to graduation, and that involved lots of data. We had a number of screens in the app that were merely large data entry screens. Binding errors where a problem, and it seemed like a new batch showed up every time we made a release to the users.&lt;/p&gt;  &lt;p&gt;The errors might have been the result of renaming a bound property, bad spelling, or some other such silliness. They were easy mistakes to make and thus I began to think that we really needed a way to automatically test them.&lt;/p&gt;  &lt;p&gt;Well, I’m lazy and time passed (maybe a year) and then I mentioned it again to Rob. The next day he committed a prototype to the &lt;a title="free WPF and Silverlight from the stone" href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; trunk. (&lt;a title="No, Ayende and Rob are not Jesus, but I couldn&amp;#39;t resist the allusion." href="http://www.youtube.com/watch?v=jQcNiD0Z3MU" target="_blank"&gt;He’s like my own personal Ayende&lt;/a&gt;.)&lt;/p&gt;  &lt;p&gt;Here’s an example test copied directly from Caliburn’s &lt;a href="http://www.codeplex.com/caliburn/Wiki/View.aspx?title=Unit%20Testing%20Data%20Bindings&amp;amp;referringTitle=Table%20Of%20Contents" target="_blank"&gt;documentation&lt;/a&gt;:&lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public class TestBase
{
    static TestBase()
    {
        var app = new MyApplication();
        app.InitializeComponent();
    }
}&lt;/pre&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class TestCase : TestBase
{
    [Test]
    public void Test()
    {
        var validator = Validator.For&amp;lt;MyUserControl, MyModel&amp;gt;();
        var result = validator.Validate();

        Assert.That(result.HasErrors, Is.False, result.ErrorSummary);
    }
}&lt;/pre&gt;

&lt;p&gt;In TestBase, we initialize the actual application so that we have access to application level resources. We need to this in a static constructor because we don’t want more than one instance of the application in the AppDomain. &lt;/p&gt;

&lt;p&gt;Now, check out the Test() method. The static class Validator.For&amp;lt;T,K&amp;gt;() method returns an instance of BindingValidator&amp;lt;K&amp;gt;. The type T is some FrameworkElement that contains the bindings we’re interested in and K is the type that the FrameworkElement is bound to. Calling the Validate() method causes Caliburn to instantiate T, crawl it’s tree, and collect all the bindings. It then compares those bindings to the type K to see if they are valid. Validate() actually returns an instance of ValidationResult&amp;lt;K&amp;gt;, which is a summary of everything that Caliburn found while comparing the bindings against the actual type T. &lt;/p&gt;

&lt;p&gt;The assertion in the test means that we expect Caliburn to find no errors, and if it does to provide us the summary. This is useful because there might be a number of binding errors and the ErrorSummary will give us the whole list.&lt;/p&gt;

&lt;p&gt;At this point, I’m just repeat what’s stated in Caliburn’s documentation. &lt;a title="you know you want it!" href="http://nhprof.com/" target="_blank"&gt;NH Prof&lt;/a&gt; was the first project where we’ve actually used the Testability features of Caliburn. Let’s check out a real live test from it:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[TestFixture]
public class MessageBoxViewTextFixture : ViewTestFixtureBase
{
    private readonly ValidationResult&amp;lt;MessagePresenter&amp;gt; bindings;

    public MessageBoxViewTextFixture()
    {
        bindings = Validator.For&amp;lt;MessageBoxView, MessagePresenter&amp;gt;()
            .Validate();
    }

    [Test]
    public void BindingsDoNotHaveErrors()
    {
        Assert.That(bindings.HasErrors, Is.False, bindings.ErrorSummary);
    }

    [Test]
    public void MessageIsBound()
    {
        Assert.That(bindings.WasBoundTo(x =&amp;gt; x.Message));
    }
}&lt;/pre&gt;

&lt;p&gt;This test is for the view that displays a simple popup message. We have a simple presenter that backs the view and it has a message to display in its property Message. It’s tested independent of the view. (This is nice because we have a case in NH Prof where a single presenter might be bound to multiple views.)&lt;/p&gt;

&lt;p&gt;The ViewTestFixtureBase is identical to TestBase from the example above. Since it’s expensive to have Caliburn instantiate and crawl the UI validating the bindings, we only want to do this once. (I’m not really sure why I used the constructor, instead of [TestFixtureSetUp], but I did.) &lt;/p&gt;

&lt;p&gt;The first test covers 90% of what you typically need, catching spelling errors, etc. The second test however explicitly checks to see if we are bound to the Message property on the presenter. This is useful because that’s the core reason for this view. There may be other properties bound, but this is the one we definitely care about. (I think this affords liberty to designers while ensuring that a view delivers the business value that was intended.)&lt;/p&gt;

&lt;p&gt;Now, let’s pretend that I have a bad binding in my markup. Here’s the core snippet for the view used in the test above, MessageBoxView:&lt;/p&gt;

&lt;pre class="xml:nogutter:nocontrols" name="code"&gt;&amp;lt;Grid MaxWidth=&amp;quot;260&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBlock Foreground=&amp;quot;{StaticResource Text}&amp;quot; 
                   FontSize=&amp;quot;14&amp;quot;
                   TextWrapping=&amp;quot;Wrap&amp;quot;
                   Text=&amp;quot;{Binding Messyage}&amp;quot; /&amp;gt;
        &amp;lt;Button Content=&amp;quot;OK&amp;quot;
                Margin=&amp;quot;4 8 4 4&amp;quot;
                HorizontalAlignment=&amp;quot;Center&amp;quot;
                IsCancel=&amp;quot;True&amp;quot; /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;    
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;

&lt;p&gt;Oops, I misspelled Message in the binding! When I execute my tests, they both fail. The first because there is a binding error and the second because it can’t find Message. Here’s the actual exception from the first test:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;NUnit.Framework.AssertionException:&amp;#160;&amp;#160; [MessageBoxView.Grid.StackPanel.TextBlock] The property &amp;#39;Messyage&amp;#39; was not found on &amp;#39;MessagePresenter&amp;#39;. 
    &lt;br /&gt;&amp;#160; Expected: False 

    &lt;br /&gt;&amp;#160; But was:&amp;#160; True&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that it actually gives you the path to the offending binding: &lt;em&gt;MessageBoxView.Grid.StackPanel.TextBlock&lt;/em&gt;. Now that’s just cool! Thanks Rob!&lt;/p&gt;

&lt;p&gt;I can’t explain how much pain it saves to be able to do this. If you are doing TDD with WPF, you really need to check this out.&lt;/p&gt;

&lt;p&gt;I’ll post over the weekend some tests that are a bit more BDD in their styles.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=44397" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI+Patterns/default.aspx">UI Patterns</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/XAML/default.aspx">XAML</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category></item></channel></rss>