Having trouble with Form.AcceptButton?

Recent explorations of WPF have caused me to revisit things I used to avoid in .NET. I’ve spent a lot of time over the past week or so working with the TableLayoutPanel and FlowLayoutPanel, and I never really realized how much I dislike the designer for some nitpicky alignment things. I made a relatively complicated application to test myself, and though there’s some lingering issues in Windows Forms 2.0 it looks like WPF solves most of them.

The big thing that has been bugging me is I made a dialog to edit program settings, and when I added the “OK” and “Cancel” buttons I set the form’s AcceptButton and CancelButton properties appropriately. However, when I tried the form out, I found that the cancel button worked perfectly but the OK button did nothing. I decided that perhaps I had left something out of my layout logic, so I started a new project and used the designer to set up a simple dialog with a text box and the two buttons; this dialog worked so I figured I’d done something wrong. I decided I’d just make the button’s click event set DialogResult and left the issue alone.

Then today, someone on the VB .NET forum I frequent posted a problem with the AcceptButton property that was exactly opposite of mine: they didn’t want the button to respond to the Enter key or close the dialog. I decided that the answer to his question was probably pertinent to mine, so I revisited the example. This time, I managed to do something in the designer that caused the OK button to not work properly. I was mystified, so I asked the guy on the forums to post some of his code so I could try to figure out what was different. The answer turns out to be a combination of the Button class’s DialogResult property and an oversight on the part of Microsoft.

I wrote a test program to examine the DialogResult property before and after assigning buttons to a form’s AcceptButton and CancelButton properties. CancelButton worked exactly as I expected and changed the button’s DialogResult property to DialogResult.Cancel. However, AcceptButton did not alter the button’s DialogResult property at all. I double-checked this in Reflector and found that the property set method for AcceptButton doesn’t do anything at all with the button’s DialogResult property.

So if you are having trouble with getting the OK button of a dialog to work, and the only step you are taking is to set the form’s AcceptButton property, be sure to always manually set the button’s DialogResult property. AcceptButton‘s property set method does call UpdateDefaultButton, a protected method of Form with no default implementation. It’s possible you could override this method and add the line:

this.AcceptButton.DialogResult = DialogResult.OK

However, since it’s a protected method that is used by the default implementations of the Form class it’s probably a bad idea to assume this will always work. In particular, if they swap the order of the lines of code it will fail. Perhaps you could override the AcceptButton property and call the base implementation, but that’s still kind of icky. I have not tested this in .NET versions later than 2.0, but I doubt it has been fixed.