Home > View Post

I heart PropertyGrid

It might not be the prettiest control in the world and it might seem a little 'generic' for most user interfaces but I love the PropertyGrid control in .NET winforms.

I find it particularly useful for any settings or configuration screens in my WinForm apps, such as the custom UI for the SSIS Compress File Task I published recently:

Compress File Task Settings Dialog

The best thing about it is all the things you get for free:

  • Automatic validation of input: if the type is an Int32 the user can only enter an Int32
  • Automatic discovery of properties: just point it at your class and it will create the UI for you
  • Enums appear as dropdowns

On the other hand, the downside is that you don't have enough control over what is displayed. This happened with the Compress File task where I only wanted a handful of the properties available. Sure, you can start playing with all the System.ComponentModel attributes but things quickly start to clog up - and inheritence could throw a spanner in the works.

The solution is to wrap your class in a simple facade. Imagine this is the class that we want to 'configure'

public class SimpleTask : Task
{
    public string ConnnectionName { get; }
}

Now if we were to point this at a PropertyGrid we'd get all the 'junk' we've inherited from Task. But we only want the user to configure the ConnectionName property. All we have to do is create a simple facade that only presents the properties that we choose:

public class SimpleTaskConfiguration
{
    private SimpleTask _simpleTask;
    private string _connectionName;
    
    public SimpleTaskConfiguration(SimpleTask simpleTask)
    {
        _simpleTask = simpleTask;
        _connectionName = _simpleTask.ConnectionName;
    }
    
    public string ConnectionName
    {
        get { return _connectionName; }
        set { _connectionName = value; }
    }
    
    public void Save()
    {
        _simpleTask.ConnectionName = _connectionName;
    }
}

So we simply construct an instance of SimpleTaskConfiguration specifiying the instance of the SimpleTask we actually want to modify and pass that as the SelectedObject for the PropertyGrid. We could even use the facade to change the 'shape' of the target class, for example, bring sub properties to the top level.

We've also managed to squeeze in a couple of extras here too... notice the Save method? Well, your settings dialog will probably have an OK and a Cancel button which means you want to support the ability to drop any changes made. Now this is really easy because I only call Save (which writes the values back to the original object) if the user clicks OK, e.g.:

public class SettingsDialog : Form
{

    ///... blah ...

    private void _btnOK_Click(object sender, EventArgs e)
    {
        _simpleTaskConfiguration.Save();
        DialogResult = DialogResult.OK;
    }
    
    private void _btnCancel_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.Cancel;
    }
}

I use subtle variations on this pattern all the time and not just for SSIS tasks. In particular, I use it a lot for custom user settings in winforms apps where, instead of writing to some parent object, the Save method persists the settings class to disk using the XmlSerializer.

The PropertyGrid isn't perfect for all scenarios (far from it) but it can help you to create really quick and neat UI to manage some simple settings.

Now, if this post seems a little out of the blue it's because it's laying the foundation for my next little pet project, which I'll be posting about soon. Stay tuned.

PS - If you want to see an example of the above download the source code for the Compress File Task. If you'd like an example of persisting user settings to disk, just drop me a line.

Tags: .NET

 
Josh Post By Josh Twist
5:31 AM
18 Jul 2006

» Next Post: Elegant conditionals in your UI
« Previous Post: Not everybody has superhuge monitor

Comments are closed for this post.

© 2005 - 2017 Josh Twist - All Rights Reserved.