A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy, an automated deployment tool for .NET applications.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

When building an application, I might not have the luxury of creating model classes to represent the objects I'll be rendering on screen, because they are dynamic. If I don't know the shape of my data, I can use a meta model (a model of the final model) to represent it.

Some examples of where this exist are:

  • SharePoint - users can define custom lists with custom columns, so a particular ListItem has many "properties"
  • Microsoft CRM - users can define custom entities, again with custom attributes

For example, I might have the concept of a Property:

public class Property : INotifyPropertyChanged
{
    public Property(string name, object value)
    {
        Name = name;
        Value = value;
    }

    public string Name { get; private set; }
    public object Value { get; set; }
}

And the concept of a Record, which is really just a bag of properties:

public class Record
{
    private readonly ObservableCollection<Property> properties = new ObservableCollection<Property>();

    public Record(params Property[] properties)
    {
        foreach (var property in properties)
            Properties.Add(property);
    }

    public ObservableCollection<Property> Properties
    {
        get { return properties; }
    }
}

Here's how I might fill the data:

var records = new ObservableCollection<Record>();
records.Add(new Record(new Property("FirstName", "Paul"), new Property("LastName", "Stovell")));
records.Add(new Record(new Property("FirstName", "Tony"), new Property("LastName", "Black")));

Rendering basic columns in a DataGrid

Building a DataGrid to render this model is pretty easy. The XAML would be:

<DataGrid 
   Name="dataGrid" 
   AutoGenerateColumns="false" 
   ItemsSource="{Binding Path=Records}" 
   />

Since I don't know the names of the columns at design time, I'll have to dynamically generate them. This part is easy:

var columns = records.First()
    .Properties
    .Select((x, i) => new {Name = x.Name, Index = i})
    .ToArray();

foreach (var column in columns)
{
    var binding = new Binding(string.Format("Properties[{0}].Value", column.Index));

    dataGrid.Columns.Add(new DataGridTextColumn() {Header = column.Name, Binding = binding });
} 

As you can see, I dynamically create a Binding, and use the index of the column in my model as the binding path.

Rendering templated columns

This part gets harder. If I wanted to use a custom CellTemplate to render my properties, I might have done this in XAML:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Border Padding="3" Background="Purple">
                <TextBox Text="{Binding Path=FirstName}" />
            </Border>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Notice I hardcoded Path=FirstName in the binding above - that's not going to work when we have a dynamic model.

It took a lot of experimentation to make this happen, but the result isn't much more complicated. I'd start by making a DataTemplate for the cell as a resource:

<Window.Resources>

    <DataTemplate x:Key="CustomTemplate">
        <Border Padding="3" Background="Purple">
            <TextBox Text="{Binding Path=Value}" />
        </Border>
    </DataTemplate>

</Window.Resources>

I'd then dynamically generate the columns like this:

foreach (var column in columns)
{
    var binding = new Binding(string.Format("Properties[{0}]", column.Index));
    dataGrid.Columns.Add(new CustomBoundColumn() 
    { 
        Header = column.Name, 
        Binding = binding, 
        TemplateName = "CustomTemplate" 
    });
} 

The part that makes it work is the CustomBoundColumn - I had to implement this myself. Here it is:

public class CustomBoundColumn : DataGridBoundColumn
{
    public string TemplateName { get; set; }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var binding = new Binding(((Binding)Binding).Path.Path);
        binding.Source = dataItem;

        var content = new ContentControl();
        content.ContentTemplate = (DataTemplate)cell.FindResource(TemplateName);
        content.SetBinding(ContentControl.ContentProperty, binding);
        return content;
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        return GenerateElement(cell, dataItem);
    }
}

Note that the name of the DataTemplate is passed as a property to the CustomBoundColumn, so you could dynamically choose a DataTemplate to use based on the type of property (e.g., use a different template if the value is numeric).

I just answered a question on StackOverflow, where my answer involved using named controls in a ControlTemplate. It occurred to me that many WPF developers might not be aware of the feature, even though they've probably used it before.

Suppose you're an intern at Microsoft, and you've been told to implement the TextBox feature for WPF. It's complicated:

  • You need to handle selection of text, including commands like Ctrl+A
  • You need to handle copy/paste
  • You need to handle multiple languages and input methods
  • You need to position a caret between letters to show where the next keypress will be inserted

That's complicated enough. Then the pesky Expression Blend team approach you and add to the list:

  • Users should be able to override everything about how the TextBox is displayed

Let's take a TextBox, and add a custom control template, to make it look like a Search box:

<TextBox>
    <TextBox.Template>
        <ControlTemplate TargetType="TextBox">
            <Border>
                <DockPanel>
                    <Image Source="Search.png" DockPanel.Dock="Right" />
                    <ScrollViewer />
                </DockPanel>
            </Border>
        </ControlTemplate>
    </TextBox.Template>
</TextBox>

If you run the example above, it will work, but you won't be able to type in the TextBox.

Now, putting your intern cap on, you need to implement the 'caret' feature - you have to put a vertical bar somewhere to show where the next character will be inserted.

Where would you render the caret? On top of the Image? In the ScrollViewer? What if I had added 5 ScrollViewers? Clearly, you need an anchor point - a place where you know the text should go.

So the TextBox makes an assumption. You can do anything you like in the ControlTemplate, but you have to remember to add a control with a specific name - in this case, PART_ContentHost.

Let's fix our template:

<TextBox>
    <TextBox.Template>
        <ControlTemplate TargetType="TextBox">
            <Border>
                <DockPanel>
                    <Image Source="Search.png" DockPanel.Dock="Right" />
                    <ScrollViewer Name="PART_ContentHost" />
                </DockPanel>
            </Border>
        </ControlTemplate>
    </TextBox.Template>
</TextBox>

Now I can type in the TextBox.

The reason for this is that inside the TextBox, there's some code that looks (simplified) like this:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    anchor = Template.FindName("PART_ContentHost", this);
    // Store the anchor, so we can position the caret over the top of it later
}

Of course it's messier, since the Template could be set to null, and you might have to unhook events on the old anchor, but you get the idea.

How do you know about these magical strings, like PART_ContentHost? They are applied using the TemplatePart attribute.

TextBoxBase, for example, is declared something like this:

[TemplatePart(Name="PART_ContentHost", Type=typeof(FrameworkElement))]
public abstract class TextBoxBase : A500TypeDeepHierarchyOfClasses, IButNoInterfaces

You'll also usually find them in the documentation - for an example, see the TextBox Parts section on the TextBox styling documentation.

Towards the end of last year, Artem Govorov (@ArtemGovorov) and I built a WPF touch screen kiosk application for Xstrata Coal in Queensland. The client was kind enough to give me permission to publish some screenshots.

Safety is important in the mining industry, and they keep a lot of documentation. Most of these documents are kept on the company's intranet. This touch screen software will be deployed to mine sites around around Queensland, and will give employees the ability to walk up, find and print a document direct from the company intranet.

These slides were put together at the end of the first three weeks, when the bulk of the development was done. A few other developers from Readify have worked on the kiosk since, adding features and making changes, and the kiosk is being rolled out as we speak.

An article in The Australian newspaper got me very excited:

The BYO (bring your own) device program at one of Australia's largest insurers means staff will be able to break free from the shackles of their company-issued PCs and plug in their personal laptops, tablets and smartphones into the enterprise network.

"We can supply you with desktops here, but if people want to bring in their Macs or other devices, then that's their choice. People should use the device they feel the most productive in.

"It is part of Suncorp's fundamental strategy to attract, develop and retain top talent and to give them a great place to work, and try to inspire them to do great things." Mr Smith said Suncorp's goal was not to have infrastructure be a constraint to people's innovation and ingenuity.

I tend to work for lots of clients during a year, usually from their offices. I'll arrive, meet the team, and I'm excited to get started. Then I meet my desktop. It's a Pentium IV, with 1GB of memory, running Windows XP with a 7200 RPM (if I'm lucky) spinning chunk of rust. Hardware is expensive, and good computers aren't laying around in most organizations, so temporary workers like me tend to get to experience the joys of using a computer designed for 2004 in the year 2011. "This was the only machine we could find on short notice" is the usual explanation.

While the company-issued desktop is taking 15 minutes to compile the solution, and struggles to have two instances of Visual Studio open, my dual core, 8GB memory machine running a modern operating system sits in my backpack. Although my laptop is superior to the company issued workstation almost every single time, I'm never allowed to plug it into their network and use it, no matter how much it might increase my productivity.

While frustrating, I can usually understand the reasons why:

  • Computers cost money. Most companies won't buy top-of-the-line hardware to sit around in case someone like me swings by for a few weeks.
  • Protection. I can't plug my laptop in to the corporate network: I could have viruses (though given USB devices seem to work fine, this is probably moot)
  • Credentials. Who am I? I probably can't/don't want to join my computer to the corporate domain, which is necessary for a lot of software to work.
  • Data security. Since it's my laptop, I might walk out of the office with customer data on my disk. This poses a long list of legal problems (though again, a USB drive is probably just as dangerous).
  • Support. What if I'm running the wrong version of Office? I might flood their helpdesk with questions.
  • Not their problem. Due to the way most organizations are structured, IT is a cost centre that needs to be minimized. Their KPI is keeping things running, not enabling me to be productive.

Suncorps move is

Microsoft just released IE 9. You can tell when Microsoft are serious about a product release when they do it using yet another focus-group inspired website that will be offline before the end of the year (anyone remember the NetFX3 site?).

Here are some of IE 9's new features:

  • They stole the combined address bar/search box from Chrome
    (But they put it in the wrong place, so you have to choose between having more than 3 tabs open at once and being able to see the address of the web site you're looking at)
  • Font rendering powered by Microsoft's patented Horse Manure Font Rendering Engine.

You might have heard of the Horse Manure Font Renderer before - it was the most hated feature of WPF 3.0 when it shipped.

Here's the engine in action (IE 9 on the left, Chrome on the right):

IE vs Chrome rendering

The font rendering problem in WPF was very tricky - few people preferred it, many really didn't, and most didn't notice. To me, personally, I find the text on the left very hard to read, and it gives me headaches.

It took a long time for Microsoft to acknowledge the problem in WPF, and even longer to fix it. While the problem existed, Microsoft kept insisting "I can't see the problem", it's "for the best", and it's "by design".

Internally, the WPF team took the complaints pretty seriously, and though it took forever, they did eventually fix it. The fix came in WPF 4.

I'm not just Microsoft bashing - everyone complained when Safari did this on Windows in 2007. I understand all of the reasons for it - but, on Windows, it makes text harder to read for me.

Update

As Aaron pointed out below, on some machines the difference will be less apparent. The difference seems to be down to your ClearType settings - below are some examples at different contrast levels:

Different contrast levels

As you can see, adjusting ClearType to a low/medium level means the contrast isn't so bad, but personally, I prefer the high contrast setting for Chrome/Windows. I also notice a big difference on my 24" LCD monitor and my 16" RGB LED laptop screen.

Here's how this is going to play out.

  1. Microsoft will praise the new engine, because it makes super large fonts nicer, and because zooming is better. They'll conveniently forget that on the web, people like to read text. They might even suggest it's our fault for being scared of change*.
  2. MVP's and other shills will get on board, curbing any dissent
  3. IE 10 will be released, and the problem will be fixed, sometime around 2015.
  4. Those same Microsoft employees and MVP shills will blog about how bad the rendering was in IE 9, and how we should all upgrade to IE 10.

(* - the "scared of change" argument makes me smile - Chrome releases a new version every 6 weeks, and I don't complain. Hmmm, perhaps it's because Chrome releases don't suck?)

NB: Download link finally fixed

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.

Download

jQueryPad screenshot

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.

If you want to use a different version of jQuery or reference other files, just replace the files in the Templates directory.

Hope you find it useful - feature suggestions are welcome.

When it comes to dealing with databases, smart .NET developers follow the unit of work pattern. In NHibernate, the unit of work is an ISession. In LINQ to SQL and Entity Framework, it's the DataContext/DbContext.

When implementing a unit of work, or in fact any object, lifetime matters. When is the unit of work created? When does it end?

When writing ASP.NET or WCF applications, the lifetime of a unit of work is usually the request/response cycle. A single ASP.NET MVC controller might touch multiple repositories, but ideally it should only involve one ISession. The request/response cycle also often serves as the database transaction boundary.

Though some ASP.NET/WCF applications may hold a unit of work open for longer than a single request/response, it's generally agreed that it is a bad idea. Request/response is almost always the perfect model.

Unit of work in rich clients

Rich client applications don't tend to be so simple. Often, the lifetime of your unit of work depends on the user experience you're implementing. Here are some examples from applications I've worked on.

Short - Unit of Work per Interaction

In this search screen, my unit of work can be very small. When the search button is clicked, I open an ISession, fetch some results, and close the session immediately. The unit of work should only be open for a few milliseconds to a second.

A search screen

This unit of work model is usually the easiest to implement, though it can mean you can't lean on the ISession for change tracking and other useful features.

Medium - Unit of Work per View

In this bulk edit screen, I might open an ISession, fetch some results, and keep the session open while the user edits the changes. When they click Save, I'll commit the ISession. My unit of work might be open for a few seconds to a few minutes.

Bulk edit

This unit of work model is tricker to implement, since you need to have well defined "close" points. If your views are Windows/Dialogs, that's easy. If you're using WPF pages, it's harder, since the page can remain in the back/forward stack for some time. You need to think hard about when the right time to close each unit of work is.

Long - Unit of Work per Workflow

In this wizard UI, I might build a unit of work that stays open for the entire business process, growing larger and larger as the user makes their way through the various screens.

A navigation centric wizard

This unit of work model is probably the hardest to manage, since you need to find a nice way to share the unit of work between views/view models. If you only have one workflow active, making your unit of work a singleton could work. But if you have multiple workflows active at once, each with their own unit of work, it's harder.

Unit of work in Magellan

Magellan, like ASP.NET MVC, encourages you to use the "short" unit of work approach by default. For example:

public class SearchController : Controller
{ 
    public ISession Session { get; set; }

    public ActionResult Search(string text)
    {
        var results = Session.QueryOver<Customer>()
            .Where(Restrictions.Like("Name", text))
            .List();

        return Page(new SearchViewModel(results));
    }
}

When a Controller is resolved, its dependencies, including an ISession, might be injected. The controller might use the session to fetch some information, populate a view model, and render a view. By the time the view appears on screen, the Controller and its dependencies, including the ISession, will have been disposed.

Generally, I've found WPF applications are much easier to implement when the unit of work is scoped to a single request.

You can make Magellan support the other two unit of work models I've described above, by making a few hacks in a custom IControllerFactory, but I'd encourage you to consider the short unit of work model.

The short unit of work model also works well if you intend to someday switch your application to go through a service layer.

Why MVC in WPF makes sense

When you use MVVM by itself, the boundary around a unit of work is never clear, and might be inconsistent from view to view.

In Magellan, you use a combination of a MVVM and MVC. The controller formalizes the scoping a request - it's perfect for navigation and invoking external services. We still use a ViewModel, but it only deals with state and behavior - integration and unit of work is managed by the controller.

The key point of this post is that unit of work in WPF applications can be more complicated than web applications. I personally find the separation that MVC encourages is a great way to make me think hard about how units of work are managed, while implementing it in a consistent way.

Here's the configuration file of an application I'm working on:

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="Repositories.ConnectionString" value="Server=(local)\SQLEXPRESS;Database=XYZ;Trusted_connection=true;"/>

    <add key="Email.Pop3Host" value="pop.gmail.com"/>
    <add key="Email.Pop3Port" value="995"/>
    <add key="Email.Pop3Ssl" value="True"/>
    <add key="Email.Pop3User" value="someone@gmail.com"/>
    <add key="Email.Pop3Password" value="password"/>
  </appSettings>
</configuration>

As an Autofac user, I use modules to structure my application. That means I have modules like:

public class EmailModule : Module
{
    public string Pop3Host { get; set; }
    public int Pop3Port { get; set; }
    public bool Pop3Ssl { get; set; }
    public string Pop3User { get; set; }
    public string Pop3Password { get; set; }

    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<EmailReceiver>().As<IReceiver>().PropertiesAutowired();
        builder.RegisterType<EmailNotifier>().As<INotifier>().PropertiesAutowired();
        builder.RegisterType<EmailParser>().As<IEmailParser>().PropertiesAutowired();
        builder.RegisterType<EmailReplyInterpreter>().As<IEmailReplyInterpreter>().PropertiesAutowired();
        builder.RegisterType<Pop3MailClient>().As<IEmailClient>()
            .WithParameter("PopServer", Pop3Host)
            .WithParameter("Port", Pop3Port)
            .WithParameter("useSSL", Pop3Ssl)
            .WithParameter("Username", Pop3User)
            .WithParameter("Password", Pop3Password);
    }
}

The convention is that any property in a module can be set by specifying an AppSetting with a key of "Module.PropertyName". That means modules aren't aware of configuration files, and not every component has to be configured in XML (the way Autofac's OOTB XML configuration works).

The ContainerBuilder is built like so:

var modules = new List<Module>();
modules.Add(new RepositoriesModule());
modules.Add(new EmailModule());
modules.Add(...);

var builder = new ContainerBuilder();
builder.RegisterModule(new ConfiguredModules(modules));

The ConfiguredModules class is a module that configures and then registers the other modules. The implementation is pretty simple:

public class ConfiguredModules : Module
{
    private readonly IList<Module> modules;

    public ConfiguredModules(IList<Module> modules)
    {
        this.modules = modules;
    }

    protected override void Load(ContainerBuilder builder)
    {
        var settings = ConfigurationManager.AppSettings;
        var keys = settings.AllKeys;

        foreach (var setting in keys)
        {
            var parts = setting.Split('.');
            var moduleName = parts[0];
            var propertyName = parts[1];
            var value = settings[setting];

            var module = modules.First(x => x.GetType().Name == moduleName + "Module");
            var property = module.GetType().GetProperty(propertyName);
            property.SetValue(module, Convert.ChangeType(value, property.PropertyType), null);
        }

        foreach (var module in modules)
        {
            builder.RegisterModule(module);
        }
    }
}

The year was 2009, and I was sick of WordPress. I was a huge fan of StackOverflow and the technology stack they were using, and thought I could "borrow" some of their ideas to create my own blog engine. After a few weeks of hacking with ASP.NET MVC 1.0, my new blog engine, PaulPad, was online. It was badly written, had few features, but it was small and simple.

After a while, Matt Hamilton and Aaron Powell started to use PaulPad too. They got sick of all the hardcoded references to "Paul Stovell" in the source code, and they started sending me patches. We figured other people might find it useful, so we renamed it FunnelWeb, and put the code on Google Code.

FunnelWeb logo

Since then, FunnelWeb has changed a lot. It's now running ASP.NET MVC 3.0 and Razor. We support extensions, themes, BlogML imports, and a truckload of features. It has grown organically, with features added by people who really wanted them. We've had contributions from almost a dozen incredibly smart people, and we're seeing lots of FunnelWeb sites popping up. Check out some of the examples on the FunnelWeb HQ site.

FunnelWeb is even proving to be a useful CMS. The MahChats website and FunnelWeb home pages are good examples - can your blog engine do that?

The best feature about FunnelWeb is that it's written in .NET, for .NET developers. If you want to change something, you can use the tools and frameworks you're familiar with. The code is relatively simple, and it's friction free.

If you're not using FunnelWeb, what would it take to get you to switch?

Working on OSS projects has been interesting not just from a code perspective, but from a community development perspective.

FunnelWeb is relatively new, and hasn't been actively promoted (I haven't even blogged about it yet). Yet check out the reply counts on some of the threads on the FunnelWeb mailing list:

My inbox, looking at the FunnelWeb discussion group

By comparison, here is what the discussion list for Magellan looks like:

Magellan's discussion list

Magellan has been around longer, and I think it's used by more people (going by download counts), yet there isn't much community participation.

Here are some observations that I think might explain the differences:

  • FunnelWeb started with three core contributors (Aaron, Matt and myself), and we're all pretty active. I never really encouraged contributors to Magellan, so it only progresses when I feel like it.
  • When people suggest features for FunnelWeb, we encourage them to submit a patch. With Magellan, I tend to end up implementing them myself.
  • As a web application, FunnelWeb has an advantage - web developers seem to be more comfortable with both using and contributing to open source. WPF developers tend to be pretty insular.
  • FunnelWeb is smaller and simpler than Magellan, so it makes it easier for people to jump in and change things.
  • Features are only added to FunnelWeb because other people want them, and they tend to be discussed a bit before code is written. Features are added to Magellan as I harvest them from my WPF projects, but there may or may not be demand for them, and I push them up without discussion.
  • As a blog engine, FunnelWeb is more likely to be used in people's spare time, so they're more likely to contribute back. Magellan is used by people at work, so they might not be able to contribute as much.

I'm curious to hear any other insights that could explain the differences in community between the two projects.

Of the two projects, I'm having a lot more fun working on FunnelWeb, thanks to the amazing community we're gathering, and the rapid improvements we're seeing. In some ways, although Magellan's source code is available and technically it's "open source", it feels less open source than FunnelWeb.