Nasty winforms bug

I've been fighting this bug all day and it annoyes me more with every minute I spend on it. Here's the deal: I have a ListView control and a Textbox control on a winforms form (.NET 1.1). With the Textbox you can edit a field of the object on the current selected row in the ListView. Easy right? I thought so too .

Not all values filled into the Textbox are valid. So I added a handler of the Validating event of the Textbox. When I tab away from the Textbox, the event gets fired and validation kicks in. If validation succeeds, the value is set in the object, otherwise validation fails and focus stays with the Textbox. When the SelectedIndex changes in the ListView and there is still a row selected, I fill the Textbox with the value of the particular field of the object currently being selected. This should work as Validating always should kick in when focus moves away from the Textbox.

But now the misery begins. Question: in which order are the following events fired when I'm editing the text of the Textbox and I click on another row in the ListView control: Textbox.Validating, Textbox.Leave, ListView.SelectedIndexChanged?

Answer: ListView.SelectedIndexChanged, Textbox.Leave, Textbox.Validating.

I'm sorry, but this is semantically wrong. What if validation fails? Focus should never move away from the Textbox before the Validating event. I now have to write some code which I consider a hack to work around this by keeping track of which object was previously selected in the ListView and I can't overwrite the 'currently selected row' when an edit is in progress, however I have to store somewhere that there is now a new selected object so after validation succeeds I have to set the Textbox to a new value.

When events were fired in the right order, this would be all fine. The low level reason for this error is the asynchronous behaviour of winform controls: under the hood they're (most of the time, there are exceptions) Win32 controls which solely respond to Win32 messages. So if you click on the ListView, the control receives a message from Windows, it acts on it and fires an event. Focus moves away from the Textbox after this and this will cause a message to be delivered for the Textbox, which will cause a .NET event. But much too late.

So if you set up a similar setup, be aware of this.

Published Friday, March 26, 2004 12:36 PM by FransBouma
Filed under:

Comments

# re: Nasty winforms bug

Friday, March 26, 2004 7:18 AM by Paul Gielens
Please highlight this in your post "asynchronous behaviour of winform controls". The whole event system suffers from this behavior. We've had similar problems and hacking around those darn events makes the whole even messier.

# re: Nasty winforms bug

Friday, March 26, 2004 7:21 AM by Frans Bouma
Will do :)

# re: Nasty winforms bug

Friday, March 26, 2004 7:28 AM by Martijn Boland
Haha, be glad you don't develop for the Compact Framework. An example:

Controls in the CF have a validating event (with CancelEventArgs) just like their Winforms brothers. When calling e.Cancel in the eventhandler nothing happens and everything continues like it's business as usual. Why would you want to cancel something in a Validating event anyway? :)

# re: Nasty winforms bug

Friday, March 26, 2004 7:53 AM by Greg Robinson
You should post this in the WINFORMS Listserv. Lots of MS folks 'listen' and reply. I'd be curious to here their reply.

# re: Nasty winforms bug

Friday, March 26, 2004 10:24 AM by Jeff Lewis
This actually happens when using the win32 api as well. It is just the order that the events get sent through the message pump...

# re: Nasty winforms bug

Friday, March 26, 2004 10:25 AM by Frans Bouma
Jeff: true, but that is an asynchronous, somewhat lowlevel environment, not the synchronous environment of .NET. I'd expect from .NET that it would be handled properly.

# re: Nasty winforms bug

Friday, March 26, 2004 1:12 PM by Johnny Hall
WinForms validation is useless anyway, I never bother with it (not that it does much for you).

Ian Griffiths discussed this before:

http://staff.develop.com/candera/weblog2/articleview.aspx/CLR%20Workings/WinForms%20Validation%20Broken.xml

# re: Nasty winforms bug

Tuesday, April 20, 2004 10:55 AM by Layton Smith-Perrin
.NET is crap. I can code everything that winforms or webforms do with XML and XSLT and either Java or a native server back-end in a fraction of the time with a fraction of the effort, hassle, and bugs.

What was MS thinking? Why do people continue to bypass perfectly good and workable technologies to use the latest buggy insecure trash from Microsoft?

# re: Nasty winforms bug

Wednesday, May 05, 2004 2:11 PM by Dave Johnson
Has anybody found a fix for this problem or do they know if Microsoft is supposed to address this problem? I did some testing on this and the events are pretty messed up compared to VB6.

-------------------------------------------
Here is the VB6 flow of events going from Textbox1 to Textbox2

Text1_Validate
Text2_MouseDown
Text1_LostFocus
Text2_GotFocus
Text2_Click

Here is the VB6 flow of events going from Textbox1 to Listview1

Text1_Validate
Listview1_MouseDown
Listview1_ItemClick
Text1_LostFocus
Listview1_GotFocus
Listview1_Click

None of the events are fired after the Validate event if it is cancelled.

Here is the .NET flow of events going from Textbox1 to Textbox2

Text1_LostFocus
Text1_Leave
Text1_Validating
Text1_Validated
Text2_Enter
Text2_GotFocus
Text2_MouseDown
Text2_Click

If the Validating is cancelled then

Text1_LostFocus
Text1_Leave
Text1_Validating


Here is the .NET flow of events going from Textbox1 to Listview1

Listview1_MouseDown
Listview1_SelectedIndexChanged
Text1_LostFocus
Text1_Leave
Text1_Validating
Text1_Validated
Listview1_Enter
Listview1_GotFocus
Listview1_Click

If the Validating is cancelled then

Listview1_MouseDown
Listview1_SelectedIndexChanged
Text1_LostFocus
Text1_Leave
Text1_Validating