views:

930

answers:

4

using c# winforms vs2008

Howdy,

ive got a textbox on a form with a method being called from the textBox1_Leave event. The mehtod takes the contents of the textbox in question and populates other textboxes based on the contents. My problem is that is the user has focus on the text box then clicks the button to close the form (calling this.close) then the form does not close becasue the textbox leave event gets fired. If the textbox does not have focus on form close then the form closes fine.

If however a user closes the form by clicking the little X close icon in the top corner the it closes fine all the time with out the textbox leave event being fired.

How i duplicate the X close functionality so that i can always close the form without the textbox leave event being fired

thanks for any advice

A: 

you can check to see which control has just got focus.

private void textBox1_Leave(object sender, EventArgs e)
{
    if (btnClose.Focused)
        return;
    // go from here
}
Courtney de Lautour
You're close - but the focus has not yet changed in the `Leave` event.
Aaronaught
+1  A: 

The simplest solution is going to be to check which control is actually focused before doing your post-processing - but you can't do it in the Leave handler, because the focus will still be on the text box at that point.

Instead, you need to move your logic to the LostFocus event, which is not in the designer. You'll have to wire it up at runtime:

public class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        textBox1.LostFocus += new EventHandler(textBox1_LostFocus);
    }

    private void textBox1_LostFocus(object sender, EventArgs e)
    {
        if (closeButton.Focused)
            return;
        // Update the other text boxes here
    }
}

The LostFocus event happens to fire after the new control receives focus.

Clarification - you might find that it works by putting this logic in the Leave event - if the focus is changed by the mouse. If the keyboard is used instead, you'll get the wrong behaviour. LostFocus is reliable in both cases - the focused control will always be the "new" control. This is documented on MSDN: Order of Events in Windows Forms.

Incidentally, the reason why you're not having this problem with the "red X" is that the X is not actually a control that can receive focus, it's part of the window. When the user clicks that, it's not causing the text box to lose focus, and therefore isn't causing the Leave event to fire.

Aaronaught
I disagree with the comment about `Leave` giving incorrect behaviour, see - http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx (incidentally the focused parameter is changed before the receiving control invokes `Enter`, which comes first in the event order)
Courtney de Lautour
Depending on the functionality needed, there can be a problem with this approach too. If the close button is next in the tab order after the text box, and the user presses TAB to leave the text box, this will keep the updates you want from occurring, even though they should be.
Robert Rossney
Ill give this way a go and see how its likethanks everyone for the input
Spooky2010
@Robert Rossney: That seems to be the desired behaviour here, not a problem; there's evidently some logic that's firing when the text box loses focus and he doesn't want that to be fired when the user wants to close the form, which would include tabbing to the close button if it's next in line. A "complete" solution would fire the same logic when the Close button loses focus, unless the focus is being changed back to the original text box.
Aaronaught
@Courtney: As I explained, the focused control is only changed at that point in time when it's a mouse action; your program has to work for keyboard actions as well. I'm frequently frustrated at the number of programs I use that haven't tested keyboard navigation properly and do things like mess up tab order.
Aaronaught
My apologies, when I tested this (before posting an answer) I got the results I expected (logic preformed unless closing the form via the button), as you point out if you use the 'Leave' event, the button doesn't have focus yet (if you've navigated by keyboard) so the logic will still be preformed (Roberts comment) which I thought would be the desired behavior.
Courtney de Lautour
A: 

Another approach: Use the textbox's validating event instead of it's leave event, then change the button's CausesValidation property to false. You will also have to set the textbox to not cause validation in the button's click event so the validating event will not fire when the form is closing (thanks to @Powerlord for pointing this out).

private void button1_Click(object sender, EventArgs e)
{
    this.textBox1.CausesValidation = false;
    this.Close();
}
thedugas
The Validating event also fires on form close.
R. Bemrose
@Powerlord - your right, I edited to include setting the textbox inside the button's click event to not cause validation.
thedugas
A: 

You could also handle the FormClosing event and make sure the e.Cancel argument does not get set to true by the validating events on the other controls on the form. I think they will be fired off before the FormClosing event.

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {   
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = false;
                return;
            }
        }
jomtois