Behfar Baghovvat
Behfar Baghovvat

Reputation: 1

How in C # we can focus on a text box?

In C #, I defined a class called ( Utility ) in which I defined a set of functions that I can use inside the program.

I defined an email template check function that's apparently grammatically fine. If I use the extension ( .com ) in the program, it is not a problem, but we get into trouble when we use an extension other than ( .com ). In this case, it is not possible to leave our control box. Can you help me figure out what the problem is?

private static string[] formatEmail = new string[4];

public static void CheckFormatEmail(System.Windows.Forms.TextBox textBox, 
System.Windows.Forms.ErrorProvider errorProvider)
    {
        formatEmail[0] = ".com";
        formatEmail[1] = ".org";
        formatEmail[2] = ".ir";
        formatEmail[3] = ".net";

        int indexChar = 0;
        int lenght = 0;
        string subString = null;
        string suffix = null;

        if ((textBox.Text).Contains("@"))
        {
            for (int i = 0; i < formatEmail.Length; i++)
            {
                if (!textBox.Text.EndsWith(formatEmail[i]))
                {
                    textBox.Focus();
                    textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
                    errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
                }
                else
                {
                    suffix = formatEmail[i];
                    indexChar = textBox.Text.LastIndexOf('@');

                    if (string.Compare(suffix, ".ir") == 0)
                    {
                        lenght = (textBox.Text.Length - indexChar) - 3;

                        subString = textBox.Text.Substring(indexChar, lenght);

                        if (!string.IsNullOrWhiteSpace(subString.Remove(0, 1)))
                        {
                            textBox.BackColor = System.Drawing.SystemColors.Window;
                            errorProvider.Clear();
                            ;
                        }
                        else
                        {
                            textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
                            errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
                            textBox.Focus();
                            break;
                        }
                    }
                    else
                    {
                        lenght = (textBox.Text.Length - indexChar) - 4;

                        subString = textBox.Text.Substring(indexChar, lenght);

                        if (!string.IsNullOrWhiteSpace(subString.Remove(0, 1)))
                        {
                            textBox.BackColor = System.Drawing.SystemColors.Window;
                            errorProvider.Clear();
                            return;
                        }
                        else
                        {
                            textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
                            errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
                            textBox.Focus();
                            break;
                        }
                    }
                }
            }               
        }
        else
        {
            textBox.Focus();
            textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
            errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
            return;
        }
    }

Upvotes: 0

Views: 132

Answers (1)

Dai
Dai

Reputation: 155145

Rather than try to fix your code, I'll say that you're doing it wrong at a fundamental level by reimplementing your own e-mail address validation logic - which is already a solved problem with countless of solutions.

So don't reinvent the wheel, just do this:

using System;
using System.ComponentModel.DataAnnotations;
using System.Net.Mail;
using System.Windows.Forms;

public static class MyValidationMethods
{
    public static void ValidateEmailAddressTextBox( TextBox textBox, ErrorProvider err, Boolean focusOnError )
    {
        if( textBox is null ) throw new ArgumentNullException(nameof(textBox));
        if( err is null ) throw new ArgumentNullException(nameof(err));

        //

        if( TryValidateEmailAddress( textBox.Text, out MailAddress? addr ) )
        {
            err.SetError( textBox, "" ); // Don't use `Clear()` for a single control, instead use `SetError()` with an empty message.

            String dnsHostName = addr.Host;
            String[] dnsLabels = dnsHostName.Split('.');
            // TODO: If you really want to filter or restrict e-mail DNS names then you can do that here by doing case-insensitive matches on the last 2 or 3 elements in `dnsLabels`.
        }
        else
        {
            err.SetError( textBox, "\"${textBox.Text}\" is not a valid e-mail address." );
            if( focusOnError ) textBox.Focus();
        }
    }

    // NOTE: If you're targeting .NET Core or later (e.g. .NET 5, .NET 6, etc) then be-aware that `EmailAddressAttribute` was changed to only perform very simplistic (almost useless!) validation instead of using its previously stricter regex.
    // * See:
    //      * https://github.com/dotnet/corefx/pull/4319
    //      * https://github.com/dotnet/runtime/issues/20884
    // * However this code below (in `TryValidateEmailAddress`) still okay on .NET 5+ because the `MailAddress` constructor still performs its own (unchanged) validation and will throw an exception (which is instantly caught).
    //     * Though it *does* accept e-mail address strings with a display-name component, e.g. `"Something" <username@host>"`.
    //     * If you want to disallow that then a quick-fix is to reject the string if it contains double-quotes. This is included in the code below within the `#if NET5_0_OR_GREATER` code.
    //        * There are limited scenarios where double-quotes are valid in an RFC email-address without a display-name, but they're esoteric and not worth handling, imo.

    private static readonly EmailAddressAttribute _validator = new EmailAddressAttribute();

    private static Boolean TryValidateEmailAddress( String inputEmailAddress, [NotNullWhen(true)] out MailAddress? addr )
    {
        
#if NET5_0_OR_GREATER
        if( _validator.IsValid( inputEmailAddress ) && !inputEmailAddress.Contains('"') )
#else
        if( _validator.IsValid( inputEmailAddress ) )
#endif
        {
            try
            {
                addr = new MailAddress( inputEmailAddress  );
                return true;
            }
            catch( Exception ex ) when ( ex is ArgumentException || ex is FormatException )
            {
            }
        }

        addr = null;
        return false;
    }
}

I made the .Focus() call conditional via the Boolean focusOnError method parameter so you can validate multiple controls at-once without needing to .Focus() on a single specific control.

For as usage example, I assume you have a method to validate all controls-at-once (ValidateEverything below), in addition to a [Control.Validatingevent-handler][1] namedEmailAddressTextBox_Validating, and that your ErrorProvidercontrol is namedformErrors`) and represents errors for multiple controls instead of just 1.

public partial class MyForm : Form
{
    private TextBox       firstEmailInputTextBox;
    private TextBox       anotherEmailInputTextBox;
    private ErrorProvider formErrors;

    // [...]

    // Uses `focusOnError: true`:
    private void EmailAddressTextBox_Validating( Object sender, CancelEventArgs e )
    {
        TextBox tb = (TextBox)sender;

        MyValidationMethods.ValidateEmailAddressTextBox( tb, this.formErrors, focusOnError: true );
    }

    // Uses `focusOnError: false` to avoid breaking the UX:
    private void ValidateEverything()
    {
        MyValidationMethods.ValidateEmailAddressTextBox( this.firstEmailInputTextBox, this.formErrors, focusOnError: false );

        MyValidationMethods.ValidateEmailAddressTextBox( this.anotherEmailInputTextBox, this.formErrors, focusOnError: false);
    }
}

As for why you're having issues with .Focus(), it's because you're inconsistently mixing break and return inconsistently - but if you simplify your logic (as done in my answer) it removes the problem entirely.

Upvotes: 1

Related Questions