Using the Command Pattern in Windows Forms clients

I’ve been doing a lot of research with the Command pattern lately at work. Here’s what I found: You’re doing yourself a disservice – and your team – if you don’t play the hell outta this thing!

It’s a very powerful design for non-trivial Windows Forms clients. What’s non-trivial? Anything that uses a menu, toolbar or context menu to show perform the same action. In fact it’s so useful and so powerful that I’m a little disappointed that Microsoft didn’t provide something like it in the framework itself. They’ve provided something in Avalon WPF, but I haven’t had the chance to play with it. I know they use it: Visual Studio and Office take advantage of it. (For example, think of how many ways you can copy and paste text.)

What are some of the advantages?

  • Automation – how easy is it to automate tasks in Visual Studio with a macro? Or reassign a keyboard shortcut? Enough said.
  • Completely decouples the UI from the business objects. It’s easy to say this but really hard to do it, especially if deadlines are tight. With commands, you can keep the UI and throw away the business objects or vice versa.
  • Easily allows plugins or addins. Suppose you have a client with a unique look that you want to control, but you want to offer the ability to extend or introduce functionality to third parties. Commands allow that. It’s how Visual Studio Add-ins do it.

There are disadvantages, of course – every design has drawbacks:

  • It complicates the application design. Every pattern complicates application design; they’re used because the benefits outweigh the cost. In fact, they should only be used when the benefits outweigh the costs.
  • Using commands complicate your controls and forms. Suppose you have a button that will be used to execute a command. Do you subclass Button so that it contains a Command and override OnClick? Do you use a normal Button and handle the Click event in the form? Change Button with MenuItem. Repeat questions.
  • Debugging is a little harder. There are features in .NET 2.0 to mitigate this one.

So what does a Command look like? Well, that’s largely up to you. The bare minimum would be one method that would allow you to perform the action associated with a Command:

public interface ICommand

{

void Execute();

}

All of your concrete commands would implement this interface and when the button or menu is clicked, call command.Execute(). Easy, eh? There is a whole lot more you can do with the shared interface, however. In fact, there is a lot of common code that you can take advantage of, which is why I prefer an abstract class, like so:

public abstract class Command

{

public string Key { get; protected set; }

public string DisplayName { get; protected set; }

 

public bool Enabled { get; }

 

public abstract void Execute();

}

All the properties would have an implementation, I leave it out because I’m only concerned with API right now. We still have that abstract Execute() method, but now we have a few properties that deserve some explanation. To further separate the UI from the business logic, if the text that the user sees is associated with the command rather than the UI, then you can easily replace the commands without modifying the UI at all. This is extremely powerful when you start dealing with collections of commands that can all be handled in the same way. So that explains DisplayName.

The Enabled property is fairly obvious: there are times when it would either be impossible or just plain wrong to perform an action; in those cases, you want to disable the UI so that the action cannot be performed. I’ll come back to the Enabled property in a second.

The Key property is for when Commands are grouped together in a collection. It makes sense to store most of your commands globally with the main form in a list or map. We’ll need a way to uniquely identify them so that we can retrieve them later. That’s what the Key property is for. Go to Tools -> Options in Visual Studio, select Keyboard. There you’ll see the keys for the commands in Visual Studio, no pun intended.

Now, by itself, the above Command is very powerful. However, we’re not done. Combine the above with Data Binding in Window Forms and you have to write almost no code at all. Data Binding is a very powerful technology, which you’ll know about if you’re one of the millions of ASP.NET developers out there. In .NET 2.0, Windows Forms apps got the same treatment. I can’t cover data binding in detail in this post, so I’ll just assume you know about it. To really take advantage of Data Binding I have to modify my Command class slightly:

public abstract class Command : INotifyPropertyChanged

{

bool enabled;

string key, displayName;

 

public event PropertyChangedEventHandler PropertyChanged;

 

public string Key

{

get { return key; }

protected set { key = value; }

}

 

public string DisplayName

{

get { return displayName; }

protected set

{

if (displayName != value)

{

displayName = value;

OnPropertyChanged(new PropertyChangedEventArgs(“DisplayName”));

}

}

}

 

public bool Enabled

{

get { return enabled; }

set

{

if (enabled != value)

{

enabled = value;

OnPropertyChanged(new PropertyChangedEventArgs(“Enabled”));

}

}

}

 

public abstract void Execute();

 

protected void OnPropertyChanged(PropertyChangedEventArgs e)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

handler(this, e);

}

}

OK, I gave you the whole implementation. You’ll see that my Command class now implements the INotifyPropertyChanged interface. This allows the data binding code to update the control that has bound to the data when the data changes. You’ll note that DisplayName and Enabled will raise the PropertyChanged event. Therefore you can create a Button, hook it up to a Command with a minimum of code and let the power of data binding deal with turning the command on and off:

Button button = new Button();

Command command = new ArbitraryCommand(“My Data”);

button.DataBindings.Add(“Text”, command, “DisplayName”);

button.DataBindings.Add(“Enabled”, command, “Enabled”);

button.Click += delegate { command.Execute(); };

This technique is very powerful when your business objects change on their own without user interaction.

There are few things you have to note. The DisplayName property will have to be internationalized if your app is interested in the rest of the world, which will make the class more complex. Also, the Command pattern kind of falls down when you need to pass data to the command. You lose the polymorphism of the Command class when you have to either know the specific concrete type or what data must be passed to a particular command.

Still, if you are doing serious Windows Forms apps, you should consider the Command pattern.

Technorati tags: , patterns

Now playing: Santana – Just Feel Better (Feat. Steven Tyler Of Aerosmith)

Setting Up A Symbol Server in Visual Studio 2005

Through a serendipitous series of links on the ol’ intarweb, I came upon this excellent post by the always excellent Jessica (aka JFo) on setting up a symbol server in Visual Studio 2003. A symbol server allows you to debug code to which you don’t own the source. I knew you could do this, but never had the need to do it at work (I’m a library author at work). But recently, I’ve been writing my own controls and I find some things are happening that I’m not expecting, so I figured I’d set this up in Visual Studio 2005. If you follow Jessica’s instructions you’ll quickly become confused, like I did: they moved the spot where you configure this.

In Visual Studio 2005, click Tools -> Options. Expand the Debugging node and select the Symbols sub-node. Click the folder icon. Type in the location of the symbols. In my case I want Microsoft’s public symbols; you can find them here: http://msdl.microsoft.com/download/symbols. Type the above as the new entry. For Microsoft’s public symbols, you’ll have to enter a folder location to cache them. You should have something like the following:

Setting up a symbol server in Visual Studio 2005

Once you click OK, you’ll have to agree to a EULA. I used Jessica’s test  from the post above to see if it was working. It wasn’t. The symbols weren’t being loaded by the IDE automatically. Maybe I did it wrong? Went back tried again; checked my settings. Nothing. Hmmm. When in doubt right-click: I found the answer on something I clicked on, I can’t remember what it was.

But I do remember the answer: there’s a setting on the General sub-node of the Debugging node of the Options dialog called Just My Code that is selected by default. That’s why the symbols weren’t loaded. De-select that setting; run Jessica’s sample app and you get the breakpoint. Yay! You’ll also note that the red dot has a + sign in it when the breakpoint is hit, unlike a break point in your code.

Technorati tags:  

Now playing: Three Days Grace – Animal I Have Become

PowerShell profile folder is different than Monad

This week, Microsoft announced Monad’s product name, PowerShell, as well as releasing an RC1 release (The very good user guide can be found here). There are quite a few changes that you can read about on their new blog: http://blogs.msdn.com/powershell. While I think Monad is just fine for a name, I like PowerShell, too. It’s much better than the other names these dummy marketers came up with. I actually have this image in my head when I think the name PowerShell that I might just blog about, but not in this post. While we’re still on naming, though, msh is a way better name for a file extension that ps1. Oh well.

Because of the name change, the profile folder in My Documents has changed but not to something intuitive, so I figured I’d post about it and hopefully let Google pick it up. The folder name for the betas was My Documents\msh. In this folder, you could put your profile script to customize the shell as well as other scripts. I posted earlier about setting the Visual Studio environment variables via script (btw, I plan on making that script better, stay tuned). That’s where you’d put those scripts.

Since the name change to PowerShell, it’d be natural to think that the folder would have to be renamed from msh to ps1, or ps. You’ll find that that is totally wrong. I think for the same reason that the .msh extension got changed to .ps1, instead of just .ps, the new folder name is My Documents\PSConfiguration.

You’ll also have to rename all of your scripts to .ps1. I tried to come up a quick little command, but I failed and just did it by hand (I only had three). I’m still stuck in the learning curve. Luckily, Peter Provost, who is far more proficient in the new shell, gives us just what we need.

Technorati tags: , , MSH

Now playing: Matthew Sweet – Sick Of Myself

WinForms Weirdness – ToolStripDropDownItem.DropDownOpening not raised in a timely manner.

I’m working on a little project to learn the ins & outs of Winforms 2.0, and I’ll be posting in the near future (well, I think I’ll be posting stuff in the near future) on the surprises and gotchas I encountered; oh, and the cool stuff, too.

The first surprise, and coolness, is with the new MenuStrip control. Menus and toolbars got a huge makeover for 2.0. We got Win98 menus in 1.1; now, we have Office 2003 menus complete with themes, textboxes, comboboxes and CommandBars. Funny that we get all those things after the Office team abandons them, which is not to say that they aren’t useful. So the feature set is way bigger, and there is some translation needed. This article on CodeProject is very helpful for that translation for menus and toolbars.

So, what’s the weirdness? Well, I want to enable/disable a menu item based on whether some object is null. I’d do this in 1.1 with the MenuItem.Popup event. The article linked above says the Popup event on the MenuItem translates to the ToolStripDropDownItem.DropDownOpening event; ToolStripMenuItem inherits from ToolStripDropDownItem. I hook up the following event handler to my ToolStripMenuItem:

        private void myToolStripMenuItem_DropDownOpening(object sender, EventArgs e)

        {

            myToolStripMenuItem.Enabled = someObject != null;

        }

Looks normal, right? And, it works, but the event is raised at, it seems, arbitrary times which isn’t what I expected. I’d open the menu, let the mouse dance around a bit, then as soon as I pointed the mouse on that menu item, it would be disabled. That’s the weirdness. You can probably tell that this is not desirable behaviour: imagine your user clicks the menu, points her mouse at your terrific new feature in the menu but when she gets to it, it becomes disabled. That ain’t cool. So, I think I’m doing something wrong; I just can’t bring myself to believe that Microsoft would ship something that broken.

Now, I was hacking away, and I didn’t want to let this stop me, so I found a workaround which demonstrates some new coolness. The MenuStrip has a MenuActivated event that’s raised before it shows the menu, so I figured I’d try that event. This time, I’d have to find my menu item and then set the property, and that is the coolness. Jessica (aka jfo) explains the keyed collection that WinForms 2.0 gives you for every control. So I hook up the following event handler to the MenuStrip.MenuActivated event:

        private void menuStrip1_MenuActivate(object sender, EventArgs e)

        {

            MenuStrip menu = (MenuStrip)sender;

            ToolStripItem[] item = (ToolStripItem[])menu.Items.Find(“myToolStripMenuItem”, true);

            item[0].Enabled = someObject != null;

And that works like a charm. The boolean parameter is for searching all children, which is what I want. Passing false there only searches the top-level menu.

Now playing: Watchmen – Any Day Now

Technorati Tags: , , ,