2
votes

I'm having a problem with validation on texbox components, in a winforms c# project.

I have several textboxes in a "Create product" form, which validates numbers, empty strings ect. If i go from one textbox (with validation) to another, the validation event fires, and i cannot change focus, i.e. im stuck at the textbox, until i type something. The behaviour i was looking for, should fire the validation events on the textboxes when i hit a "Create button", and not when i change focus from one textbox to another.

Any hints, or good practice as how to solve this? Much appreciated..

Current code:

//Validation event for one of the textboxes. epProductName is an ErrorProvider:
private void txtProductName_Validating(object sender, CancelEventArgs e)
    {
        if (Validator.IsEmpty(txtProductName))
        {
            epProductName.SetError(txtProductName, "Field must not be empty");
            e.Cancel = true;
        }
        else
        {
            epProductName.Clear();
        }
    }

//Submit button click event
private void btnSubmit_Click(object sender, EventArgs e)
    {
        if (ValidateChildren())
        {
            try
            {
                SelectedProduct.ImagePath = txtChoosePicture.Text;
                SelectedProduct.InstructionPath = txtChooseManual.Text;
                SelectedProduct.SheetPath = txtChooseDatasheet.Text;
                SelectedProduct.IsDeleted = false;
                SelectedProduct.ProductNameNum = txtProductName.Text;
                SelectedProduct.Description = txtProductDescription.Text;
                SelectedProduct.DaysToExpire = int.Parse(txtUseTime.Text);
                SelectedProduct.Category_Id = (int)cbChooseCategory.SelectedValue;

                int productId = pm.CreateProduct(SelectedProduct);

                MessageBox.Show("New Product: Id: " + productId + ", Product name: " + SelectedProduct.ProductNameNum, "New product created",
                                     MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);

                this.Dispose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Product was not created. Details: " + ex.Message, "Error",
                                 MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
        }
    }
2

2 Answers

4
votes

I recommend using the ErrorProvider control (like you already are), but not using the control's validation at all. Basically on your button press, you'll check the fields' value and then use the .SetError method on the error provider.

Another method is to use the form's ValidateChildren method. You can track whether validation should occur and only allow validation when you want it Or you can use manipulate the CausesValidation property on all your controls. Here is the first option,

    private bool _validate = false;

    private void button1_Click(object sender, EventArgs e)
    {
        _validate = true;
        this.ValidateChildren();
        _validate = false;
    }

    private void textBox1_Validating(object sender, CancelEventArgs e)
    {
           if (_validate==true)
           {
                errorProvider1.SetError(textBox1, "test");
           }
    }
1
votes

Set the CausesValidation property to false on each control to prevent it from calling the validation methods when focus leaves, explanation here for order of events:

If the CausesValidation property is set to false, the Validating and Validated events are suppressed.

Obviously you can re-enable them before calling ValidateChildren if required.