Why is there an infinite loop on my LostFocus Event

2.8k views Asked by At

I'm a beginner with C# and I'm developing a basic application.
I want to check if the value of a textbox is a number with the following code :

private void check_value(object sender)
    {
        TextBox tb = (TextBox)sender ;
        if (!Utility.isNumeric(tb.Text)){
            MessageBox.Show(tb.Text.Length.ToString());
            tb.Focus();
        }
    }

    private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
    {
        check_value(sender);
    }

When I enter a letter in the textbox there is an infinite loop and it seems that the tb.Focus() actually cause the LostFocus event to be call recursively. I don't understand why the call to the Focus method of an object triggers the LostFocus event of the same object.

3

There are 3 answers

3
Xaqron On

Opening the modal MessageBox is responsible for loosing the focus. Try hook to Validating event.

0
LePhasme On

As i said before in the link provided by Xaqron it's said that it's forbidden to use the Focus method in the LostFocus event.
And as I'm developing a WPF application there is no Validating event and CausesValidation property, so the others ways to validate the content is to use the TextChanged event or use binding validation.

Thank you for your answers.

0
Tommy Malicki On

Of course, in a perfectly valid program, you should not change Focus in the LostFocus event. This also applies to the Enter, GotFocus, Leave, Validating and Validated events, which Ms makes clear in the documentation https://learn.microsoft.com/pl-pl/dotnet/api/system.windows.forms.control.lostfocus. However, in very unusual cases, you can use the timer to trigger changes to the Focus, bypassing this problem.

private TextBox tb = null;
private System.Windows.Forms.Timer MyTimer;

private void initialize()
{
    MyTimer.Tick += new System.EventHandler(MyTimer_Tick);
    MyTimer.Enable = false;
    MyTimer.Interval = 100;
}

private void check_value(object sender)
{
    tb = (TextBox)sender ;
    if (!Utility.isNumeric(tb.Text)){
        MessageBox.Show(tb.Text.Length.ToString());
        MyTimer.Enable = true;
    }
}

private void Amount_1_LostFocus(object sender, RoutedEventArgs e)
{
    check_value(sender);
}

private void MyTimer_Tick(object sender, EventArgs e)
{
    MyTimer.Enabled = false;
    if (tb!=null) tb.Focus();
}