locked
Control.InvokeOnClick and Validation of a Form RRS feed

  • Question

  • I have a Form with a WebBrowser control on it.  Since the WebBrowser control seems to muck with certain hotkeys that I want to use on a navigation panel (full of buttons with ALT+<KEY> accelerators), I've overridden the ProcessCmdKey method of the Form and am intercepting such hotkey codes and mapping them via a hashtable to the appropriate button that I need to programmatically click.However using Control.InvokeOnClick seems to directly call the attached click event listeners rather than attempt a mouse_down followed by a mouse_up event which can be cancelled via a Control.Validating event handler's argument being set to "e.Cancel = true;" . So the problem is the Control.InvokeOnClick never causes the Form or any of its contained controls to lose focus and therefore trigger validation.  Even if I do programmatically set the focus to something else to try to trigger validation, the validation may occur, but the button click event can't be cancelled by that validation because Control.InvokeOnClick directly invokes the Click event handler callback listeners.

    I know there might be some complex solution involving using Win32 functions via the Interop classes, but I don't want to use the Interop functionality in C# cause it has been a concern with causing security problems making it harder for users to install application.

    I have tried replacing my button onclick event handlers with stub methods that call the former onclick event handlers rewritten as argumentless funcs via:

     Control.BeginInvoke(new MethodInvoker(onClickFunc));

    after first calling other code to validate and set a flag if validation failed.  Then at the beginning of my old onclick event handler (refactored to be argumentless func) I simply check the validation flag and return immediately if validation failed. However this seems needlessly complex and I'm afraid future code maintainers will be hopelessly confused.

    Any suggestions?

     

    Wednesday, November 1, 2006 5:46 PM

Answers

  • So I guess you are trying to simulate a user actually clicking on the button right? This involves not only the Click event but all the focus change events as well.

    So why don't you just simulate the button getting the focus (using Button.Select). Then you check to see if the validating event has allowed the focus change (validation succeeded) and only then do you invoke the click. Like this:

    Button1.Select();

    if(Button1.Focused)

        Button1.InvokeOnClick()

       ....

    I hope that helps

    Jero

    Wednesday, November 1, 2006 7:30 PM

All replies

  • So I guess you are trying to simulate a user actually clicking on the button right? This involves not only the Click event but all the focus change events as well.

    So why don't you just simulate the button getting the focus (using Button.Select). Then you check to see if the validating event has allowed the focus change (validation succeeded) and only then do you invoke the click. Like this:

    Button1.Select();

    if(Button1.Focused)

        Button1.InvokeOnClick()

       ....

    I hope that helps

    Jero

    Wednesday, November 1, 2006 7:30 PM
  • The above code appears to work. 

    It however assumes that Button1.Select() only returns after the following events have occurred and been processed by listeners:

    1. Cause Button1 to get the focus
    2. Cause the previous control with focus to generate a Validating event.

    of course other events occur as well, but I'm only worried about the above mentioned two.

    This also brings up the notion that event listeners in .NET aren't asynchronously decoupled from the main GUI thread, i.e. if you want something done in an event listener that might take a while and could hang the GUI you should do it on a separate thread.

    So my additional question is, can anyone guarantee that no race conditions exist that might prevent the Validating event from having already occurred and completed for the control losing focus (assuming it has its CausesValidation property set to true) before the call to Control.Focused property is made to check if the control getting the focus still has it after Validation may have cancelled it getting focus)?

    Wednesday, November 1, 2006 9:02 PM