Recently, on an internal mailing list, someone asked, “Hey Ian, you say that the Windows Forms architecture is busted. Why?” (Ian Griffiths is one of our Windows Forms experts.) Ian’s response was great, and since he doesn’t maintain a homepage at the moment, he’s allowed me to post it here. If you’re into Windows Forms at all, once you read this, you’ll probably want to run out and grab his book.
Here’s what Ian had to say:
The biggest problems with it are (1) it is based around validating one control at a time, so it has no way of dealing with validation rules that require consistency, or rules that need to look at multiple fields (e.g. 'You must supply either a work, a home, or a mobile telephone number'). (2) it is modal, which in combination with (1) means that its way of representing a failure of validation is to lock the focus into the offending control until you fix it without even telling you what's wrong. (There is the ErrorProvider control that can mitigate against the complete lack of feedback. But that actually has nothing to do with validation. (People often presume the two are linked because they are usually talked about in quick succession.) It's entirely possible to use ErrorProvider without touching the validation architecture.) The validation architecture is also not really very powerful. Unlike ASP.NET, which provides a basic toolkit of useful validation mechanisms which you can extend if you like, Windows Forms provides you with no pre-packaged validators at all. If you want regular expression validation, you have to write that. If you want 'must not be empty' validation, you have to write that. All that Windows Forms does for you is to raise the Validating event when the focus leaves the control, giving you the option to force the focus to stay in the control. (And it also raises the Validated event if nobody vetoes the Validating event.) So you're going to have to write all the code to do the actual validation yourself. Which means that all it really does is raise an event when a particular control requires validation. But it gets that wrong too... If the focus never enters a particular control on a form, that control will never be validated! Which means that if you have a form that is initially blank, but there are fields that need to be filled in, validation won't help you. One hack I've seen proposed was to loop round each control on the form calling SetFocus. But even that doesn't work so well - you have to iterate through the controls recursively because they form a tree, so you can't just do foreach(Control c in this.Controls). And it doesn't work in partial-trust scenarios - the ability to set the focus into a particular control is a privileged operation. So in practice you're going to have to write code in your OK/Apply click handler that checks all of the controls that require validation. And if you're doing that, what use is the validation architecture? You don't actually need it. Writing your own checking in the OK/Apply handler (and optionally using the ErrorProvider for feedback) is always the way to go. It means you can check fields that never even got the focus, which you can't do with the built in validation. It means you can apply validation rules that span multiple controls, which you can't do with the built-in validation. It means you don't waste time checking rules when the user clicks Cancel. (With the built-in validation architecture, you actually need to take special checks to make it possible for the user to click Cancel!) Not only is this approach more flexible and more powerful, it usually ends up involving less code... The only reason this validation architecture is in there at all is, I'm told, backwards compatibility with older versions of Visual Basic. Why on earth VB validation used to work this way is something I'll leave to the VB guys... There is only one reason for handling the Validating event. And it's not an especially good one... It turns out that this is the only way you can prevent the user from moving away from a particular tab page in a tabbed dialog. (Windows sends a special message to the application to ask if it's OK to change tabs, but Windows Forms team chose, for some reason, only to expose this via the Validating event. It's not a big problem - since the Validating architecture is really nothing more than a mechanism for preventing the user from moving the focus, then it kind of makes sense in this context. I just would have been happier if it had got its own event...)