MessageBox in Validating event cancels subsequent events

A

Al Santino

Hi,

It appears displaying a messagebox in a validating event will cancel the
subsequent event. In the program below, button 2's click event doesn't fire
if you open a dialog box in button 1's validating event. Am I doing
something wrong here?
Thanks
Al

Imports system
Imports system.windows.forms
' Create a form, add two buttons and event handlers.
' Click on Button 2 to receive Button 1 validating
' event but not button 2's click event. MessageBox
' appears to kill the click event.
Module ValidateTest
Sub Main()
Dim frm As New Form()
Dim btn As New Button
btn.Text = "One"
btn.Parent = frm
AddHandler btn.Validating, AddressOf BtnValidating

btn = New Button
btn.Left = btn.Width + 3
btn.Text = "Two"
btn.Parent = frm
AddHandler btn.Click, AddressOf BtnClick

Application.Run(frm)
End Sub

Private Sub BtnValidating(ByVal sender As Object,
ByVal e As System.ComponentModel.CancelEventArgs)
MessageBox.Show("BtnValidating event")
End Sub

Private Sub BtnClick(ByVal sender As Object, ByVal e As
System.EventArgs)
MessageBox.Show("BtnClick event")
End Sub
End Module
 
C

Chris Dunaway

Al said:
It appears displaying a messagebox in a validating event will cancel the
subsequent event. In the program below, button 2's click event doesn't fire
if you open a dialog box in button 1's validating event. Am I doing
something wrong here?

I'm not sure I understand the problem. Why would the second button's
click event be fired when the Validating event for button 1 fires?
 
A

Al Santino

Chris Dunaway said:
I'm not sure I understand the problem. Why would the second button's
click event be fired when the Validating event for button 1 fires?
Well, I thought it would fire because that was how it's supposed to work.

If you remove the MessageBox call in the validation handler the click event
fires for button 2. My understanding is that the second button's event
should fire unless you set the cancel arg to true in the validation event
handler.
 
A

Al Santino

Chris Dunaway said:
I'm not sure I understand the problem. Why would the second button's
click event be fired when the Validating event for button 1 fires?
Actually I'm not suggesting it should fire WHEN the validating event fires
but AFTER it fires since the validating event didn't set the cancel argument
to true.
 
C

Chris Dunaway

Al said:
Actually I'm not suggesting it should fire WHEN the validating event fires
but AFTER it fires since the validating event didn't set the cancel argument
to true.

Perhaps I misunderstood. Are you saying that after the validating
event fires, then the click event for the button doesn't fire, even if
you click the button?
 
A

Al Santino

Chris Dunaway said:
Perhaps I misunderstood. Are you saying that after the validating
event fires, then the click event for the button doesn't fire, even if
you click the button?
Yes. If you run the program, button 1 will start with the focus. If you
click on button 2, the button 1 validating event will fire and the program
will display the messagebox. After you close the message box, button 2 will
get the focus but its click event will not fire.
 
A

Al Santino

Chris Dunaway said:
Perhaps I misunderstood. Are you saying that after the validating
event fires, then the click event for the button doesn't fire, even if
you click the button?
Or better put:

Yes. If you run the program, button 1 will start with the focus. If you
click on button 2, the button 1 validating event will fire and the program
will display the messagebox. After you close the message box, button 2 will
get the focus but its click event will not _have fired_.
 
R

R. MacDonald

Hello, Al,

I have tried your code (VB.Net 2003) and can confirm that I see the same
(inappropriate) behaviour.

It sure looks like a problem to me. I hope someone can provide an
explanation and/or workaround.

Cheers,
Randy
 
A

Al Santino

Hi Randy,

Thanks for taking the time to try it. I'll keep my fingers crossed about
the workaround.

Al
 
C

C-Services Holland b.v.

Al said:
Or better put:

Yes. If you run the program, button 1 will start with the focus. If you
click on button 2, the button 1 validating event will fire and the program
will display the messagebox. After you close the message box, button 2 will
get the focus but its click event will not _have fired_.


From the code posted I don't see why button2's click event would be
triggered at all. The click event will not fire simply because a button
get's the focus.
 
R

R. MacDonald

Hello, Rinze,

Since the user HAS clicked on button2 with the mouse, I think this
SHOULD be enough to cause its click event to fire. Sadly, it doesn't.

Cheers,
Randy
 
C

Chris Dunaway

R. MacDonald said:
Since the user HAS clicked on button2 with the mouse, I think this
SHOULD be enough to cause its click event to fire. Sadly, it doesn't.

Now that I think about it, the button click event is not fired until
the button is *released*. Since the code is throwing up a message box,
focus is away from Button2 therefore the click is not registered.

Think about this: Suppose you had a textbox and a button on the form
and you had the validating event on the textbox. Suppose you entered
invalid data into the textbox and clicked the button, should the button
click event still be fired if the textbox was not validated?

I'm beginning to think this is by design, perhaps a bit unexpected, but
by design.
 
C

Chris Dunaway

R. MacDonald said:
Since the user HAS clicked on button2 with the mouse, I think this
SHOULD be enough to cause its click event to fire. Sadly, it doesn't.

I'm not so sure. Look at this code below. If the textbox has the word
hello in it when Button2 is clicked, should Button2's event fire
anyway? I don't think so. I think the OP's problem is because of the
Message Box. It steals focus from Button2 so that when the mouse is
release, the message is not being sent to button 2. If you remove the
Message Box from the validating event, the click event should fire.



Public Class Form1

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
MsgBox("Button 2 Clicked")
End Sub

Private Sub TextBox1_Validating(ByVal sender As System.Object,
ByVal e As System.ComponentModel.CancelEventArgs) Handles
TextBox1.Validating
If TextBox1.Text.ToUpper = "HELLO" Then
MsgBox("Invalid Value in textbox")
e.Cancel = True
End If
End Sub
End Class
 
A

Al Santino

Yes, if you remove the Message Box things work fine. But I'd like to use
this in the case where someone enters fills in some controls on a form and
then chooses to close the form. I want to give them a choice of canceling
the quit, proceeding without saving, or proceeding and saving. This seems
like a rather common behaviour.

I would expect that setting the cancel arguement to "true" would cancel the
subsequent click event and setting it to false would not.
 
R

R. MacDonald

Hello, Al,

Chris's idea that the event is being "absorbed" by the MessageBox may be
on the right track, but I suspect this is not "by design" but is more
likely due to lack of design. Either way, I can't see how to use this
idea to come up with a work-around.

But it sounds as if, rather than using the MessageBox as part of
validating the contents of a control, you are actually using it to
validate the closing of the form.

I know it doesn't address the problem of the missing click event, but
perhaps you can solve your problem by modifying your approach.

In a similar case when I wanted the user to validate or cancel
closing/saving, I have used the Form's Closing event for this purpose.
(Well actually, since it was a base for several derived forms, I
overrode the OnClosing method.) The main problem with this approach is
that it is still necessary to invoke the Validation code for the
currently ActiveControl. I haven't yet found a good generic way to do
this (in VB), and so have had to add code to each derived form to find
the active control and directly call its validation handler. (I think
it should be possible to locate and call the handler in a generic
fashion, and I'm still hoping to figure out how to do this.)

Cheers,
Randy
 
A

Al Santino

Hi Randy,

Would that it were. I have a SplitContainer with a list of items on the left
and a form on the right. When you click on an item in the list on the left
it displays the fields for the item on the right. You can edit the fields on
the right. When you click on an item in the left the form's validate event
fires to see whether you changed an item. If so, it displays a messagebox
asking whether you wish to save your changes.

I like your idea of using the form closing event but, unfortunately, the
form doesn't close each time. I do appreciate your giving this some thought.

Al
 
R

R. MacDonald

Hello, Al,

Yes, I can see that's a sticky problem. Too often in this sort of
situation we end up succumbing to non-elegant work-arounds that involve
"remembering" which control we were on, which control we were going to,
whether or not we were navigating by mouse-click, tab or code, etc. and
then programming around all the possibilities -- Very messy, because
there are usually so many possibilities.

I can't think of a good solution just now, but I'll let you know if I
have any late-night inspirations.

Cheers,
Randy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top