I've got a winforms application I am developing with VS2010. The UI consists of a tableLayoutPanel which holds seven textBoxes. I arranged tab order of the textboxes to carry the user through a logical data entry progression. Each textbox has a _Le开发者_开发百科ave event, a _Validating event, and a _Validated event. I also added a _KeyDown event for the form to make the Enter key behave like the Tab key.
private void Form1_KeyDown( object sender, KeyEventArgs e )
{
if (e.KeyCode == Keys.Enter)
{
GetNextControl( ActiveControl, true ).Focus();
}
e.Handled = true;
}
All was well at first, and each of the textboxes and events behaved as expected.
Then I added a listbox to the form, for a use case in which the user can manually enter data in the form as before, or highlight a line of pre-set data in the listbox and press a button to cause the data to transfer to the textboxes.
BUT, now several boxes on the form don't trigger the _Validating event regardless of the data entry method used. The _Leave event for the textbox is triggered, but when I step the code I find the ContainerControl.Validate() method called in the _Leave handler does not cause a branch to the _Validating (or _Validated) event handlers any more. Yet, other text boxes still work normally as before. I've examined working vs. nonworking textboxes and can see no difference in properties. I went so far as to delete a broken textbox and copy and restructure a working textbox into the same physical location. No luck!
Is there some rule against mixing controls on one form? Or is there some kind of known issue?
I should add here that I'm not using binding, but converting and parsing data to/from strings in the textboxes. This logic is spread out between the _Validating and _Validated events for each textbox.
OK, here is some more information: I instrumented the event handlers by placing Trace output at the beginning and end of each handler. While nothing jumps out as a solution, I found some interesting things. The trace statements in the _KeyDown handler were slightly different since I wanted to see when the KeyCode test was true. You can see that this trace will produce its output all on one line...
private void Form1_KeyDown( object sender, KeyEventArgs e )
{
Trace.Write( "%%% _KeyDown entered -- " );
if (e.KeyCode == Keys.Enter)
{
GetNextControl( ActiveControl, true ).Focus();
Trace.Write( "Enter key processing -- " );
}
Trace.WriteLine( " exiting" );
e.Handled = true;
}
So what happened? It makes more sense if you know that first the user types a 3-character word, presses Enter, then a two-character word, then Enter, then a 4-digit number, then Enter. Here is the transcript, with my bracketed notes:
A first chance exception of type 'System.PlatformNotSupportedException' occurred in System.Core.dll
[User types three characters and presses Enter]
%%% _KeyDown entered -- exiting
%%% _KeyDown entered -- exiting %%% _KeyDown entered -- exiting %%% _KeyDown entered -- %%% longTkrTB _Leave entered [Whoa, what's this? Leave has started in the middle of KeyDown.]%%% longTkrTB _Leave calling _Validating
%%% longTkrTB _Validating entered A first chance exception of type 'System.PlatformNotSupportedException' occurred in System.Core.dll A first chance exception of type 'System.PlatformNotSupportedException' occurred in System.Core.dll %%% longTkrTB _Validating exiting %%% longTkrTB _Validated entered %%% longTkrTB _Validated exiting[NOW the rest of the KeyDown processing occurs. Does anyone know if these events are multithreaded?]
Enter key processing -- exiting
[OK, the first textbox has been successfully processed. On to the second one, 2 chars + Enter.]
%%% _KeyDown entered -- exiting
%%% _KeyDown entered -- exiting %%% _KeyDown entered -- %%% shortTkrTB _Leave entered [Same as before, the Leave and validation process interrupts the KeyDown processing?]%%% shortTkrTB _Leave calling _Validating
%%% shortTkrTB _Validating entered %%% shortTkrTB _Validating exiting %%% shortTkrTB _Validated entered %%% shortTkrTB _Validated exiting Enter key processing -- exiting [Remainder of KeyDown processing for second textbox Enter key. The second textbox has successfully concluded. Start the 4 digits in the third textbox.]%%% _KeyDown entered -- exiting
%%% _KeyDown entered -- exiting %%% _KeyDown entered -- exiting %%% _KeyDown entered -- exiting [Now the Enter key, and things start to go haywire.]%%% _KeyDown entered -- The thread '' (0x2dc) has exited with code 0 (0x0).
Step into: Stepping over method without symbols 'System.Diagnostics.Trace.WriteLine' [Why didn't we see this message before?]%%% longVolTB _Leave entered
[OK, expected...]Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get'
Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get' Step into: Stepping over method without symbols 'Harpswell.CreatePair.PairRec.IsDummyPair.get' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.CaptureInternal.get' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.Focused.get' Step into: Stepping over method without symbols 'System.Diagnostics.Trace.WriteLine'[Well! That's a lot of processing that didn't happen with the other textboxes (unless the messages got backed up and are just now being released. If so, why don't we see many more 'Trace.WriteLine' messages?) ]
%%% longVolTB _Leave calling _Validating
[HERE is where we should enter the validation logic...]Step into: Stepping over method without symbols 'System.Windows.Forms.ContainerControl.Validate'
Step into: Stepping over method without symbols 'System.Windows.Forms.ContainerControl.UpdateFocusedControl' Step into: Stepping over method without symbols 'System.Windows.Forms.ContainerControl.AssignActiveControlInternal' Step into: Stepping over method without symbols 'System.Windows.Forms.ContainerControl.ActivateControlInternal' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.WmSetFocus' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.WndProc' Step into: Stepping over method without symbols 'System.Windows.Forms.TextBoxBase.WndProc' Step into: Stepping over method without symbols 'System.Windows.Forms.NativeWindow.DebuggableCallback' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.FocusInternal' Step into: Stepping over method without symbols 'System.Diagnostics.Trace.Write' Enter key processing -- Step into: Stepping over method without symbols 'System.Diagnostics.Trace.WriteLine'exiting
[What's this? The tail end of the KeyDown handler!]Step into: Stepping over method without symbols 'System.Windows.Forms.KeyEventArgs.Handled.set'
Step into: Stepping over method without symbols 'System.Windows.Forms.Control.OnKeyDown' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.ProcessKeyEventArgs' Step into: Stepping over method without symbols 'System.Windows.Forms.Form.ProcessKeyPreview' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.ProcessKeyMessage' Step into: Stepping over method without symbols 'System.Windows.Forms.Control.WndProc' Step into: Stepping over method without symbols 'System.Windows.Forms.TextBoxBase.WndProc' Step into: Stepping over method without symbols 'System.Windows.Forms.NativeWindow.DebuggableCallback' Step into: Stepping over method without symbols 'System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop' The thread '' (0x15f0) has exited with code 0 (0x0). The thread '' (0xc20) has exited with code 0 (0x0). The thread '' (0x11b4) has exited with code 0 (0x0).[etc.]
Forms have control order sequences such as to handle your tabbing through fields. If you added the listbox and label to describe the alternatives, that COULD mess up what you believe is the tabbing sequence... where the tab key from the table flow panel actually DOES work... it just tabs from the panel's textbox to the label or listbox.
I would check the tabbing order of the controls to make sure they are correctly sequenced.
I've found the issue, so I'm posting it here in case anyone else has this problem. I'm not sure if this is a solution or a hack, but...
I have a large number of controls on my form, between text boxes containing labels, data input text boxes, buttons, and of course the listbox and tableLayoutPanel. I mistakenly thought that those controls which contained static information like buttons, legends and the like could be marked with the property "CausesValidation=false". That mistake still seems reasonable to me.
Once I changed each and every single control with the "CausesValidation" property to "true", my problem disappeared. Evidently some of the controls' CausesValidation property were priming over onto my data entry controls, even though I saw no sign of any problem in the form1.designer.cs code-behind.
精彩评论