1
votes

I have a DataGridView that consist of some rows and columns. I want to check all cells of my DataGridView for empty cells, if any cell is empty in any row then give me a message. I have a code for doing that but it checks only the cells of the first row This is my code:

    foreach (DataGridViewRow rw in dgv_absence.Rows)
    {
        if (rw.Cells[0].Value == null || rw.Cells[0].Value == DBNull.Value || string.IsNullOrWhiteSpace(rw.Cells[0].FormattedValue.ToString()) || rw.Cells[1].Value == null || rw.Cells[1].Value == DBNull.Value || string.IsNullOrWhiteSpace(rw.Cells[1].FormattedValue.ToString()))
        {
            MessageBox.Show("message","title");
            return;
        }
        else
        {
            for (int i = 0; i < dgv_absence.Rows.Count - 1; i++)
            {
                // do some thing
            }
        }
    }
3
is this for a windows form app?Juan M. Elosegui
There are several validation events. Looping all rows is an inefficient way to check oneŇɏssa Pøngjǣrdenlarp
yes, windows formsHunar
You can use Fluent Validation if you don't want to be tight to the validation events of the framework. Also you can separate the validation process in separate project. In that way you can reuse it in another kind of project, and is not hard to set up the implementation. Check my answer here stackoverflow.com/a/40997368/819153, I use it there for a Asp.net application. Hope this helpsZinov

3 Answers

0
votes

Instead of Cells[0], which only targets the first cell of each row, you need to also loop through the cells in an inner for loop. Like this:

        foreach (DataGridViewRow row in dataGridView.Rows)
        {
            foreach (DataGridViewCell cell in row.Cells)
            {

            }
        }
0
votes

This is what I would do.

The DataGrid control on Windows Form can read errors from objects implementing IDataErrorInfo

As MSDN says.

IDataErrorInfo Provides the functionality to offer custom error information that a user interface can bind to.

Your POCO object inside the data source collection for the grid, should implement IDataErrorInfo let's say something like this:

public class MyEntity : IDataErrorInfo
{
    public string this[string columnName]
    {
        get
        {
            // here you can validate each property of your class (POCO object)
            var result = string.Join(Environment.NewLine, Validator.Validate(this, columnName).Select(x => x.ErrorMessage));
            return result;
        }
    }

    public string Error
    {
        get
        {
            // here you can errors related to the whole object (ex: Password, and PasswordConfirmation do not match)
            return string.Join(Environment.NewLine, Validator.Validate(this)
                                                                .Select(x => x.ErrorMessage));
        }
    }

    public Boolean IsValid
    {
        get { return string.IsNullOrEmpty(Error); }
    }
}

Then you could use some validation technique to set up your validation rules.

I like to use DataAnnotation to implement my validation logic.

So, let's say your class has a property (name) that cannot be null you class could be:

public class MyEntity : IDataErrorInfo
{
    [Required]
    public string Name { get; set; }

    public string this[string columnName]
    {
        get
        {
            // here you can validate each property of your class (POCO object)
            var result = string.Join(Environment.NewLine, Validator.Validate(this, columnName).Select(x => x.ErrorMessage));
            return result;
        }
    }

    public string Error
    {
        get
        {
            // here you can validate errors related to the whole object (ex: Password, and PasswordConfirmation do not match)
            return string.Join(Environment.NewLine, Validator.Validate(this)
                                                                .Select(x => x.ErrorMessage)
                                                                .Union(ModelError.Select(m => m.Value)));
        }
    }

    public Boolean IsValid
    {
        get { return string.IsNullOrEmpty(Error); }
    }
}

Then if you use a validator like this

public class Validator : IValidator
{
    public IEnumerable<ErrorInfo> Validate(object instance)
    {
        IEnumerable<ErrorInfo> errores = from property in instance.GetType().GetProperties()
            from error in GetValidationErrors(instance, property)
            select error;
        if (!errores.Any())
        {
            errores = from val in instance.GetAttributes<ValidationAttribute>(true)
                where
                    val.GetValidationResult(null, new ValidationContext(instance, null, null)) !=
                    ValidationResult.Success
                select
                    new ErrorInfo(null,
                        val.GetValidationResult(null, new ValidationContext(instance, null, null)).ErrorMessage,
                        instance);
        }

        return errores;
    }

    public IEnumerable<ErrorInfo> Validate(object instance, string propertyName)
    {
        PropertyInfo property = instance.GetType().GetProperty(propertyName);
        return GetValidationErrors(instance, property);
    }

    private IEnumerable<ErrorInfo> GetValidationErrors(object instance, PropertyInfo property)
    {
        var context = new ValidationContext(instance, null, null);
        context.MemberName = property.Name;
        IEnumerable<ErrorInfo> validators = from attribute in property.GetAttributes<ValidationAttribute>(true)
            where
                attribute.GetValidationResult(property.GetValue(instance, null), context) !=
                ValidationResult.Success
            select new ErrorInfo(
                property.Name,
                attribute.FormatErrorMessage(property.Name),
                instance
                );

        return validators.OfType<ErrorInfo>();
    }
}

The errors will appear on the grid per cell or per row depending on the error.

Notice that you should also implement INotifyPropertyChanged if you are planning to in-line editing your objects.

This approach has the benefit of decoupling the validation logic from the user interface.

0
votes

you can call this method it return if one cell is empty or not:

 public Boolean IsDataGridViewEmpty( DataGridView dataGridView)
    {
        bool isEmpty = false;
        foreach (DataGridViewRow row in dataGridView.Rows)
        {
            if (!row.IsNewRow)
            {
                foreach (DataGridViewCell cell in row.Cells)
                {
                    //if (!string.IsNullOrEmpty(cell.Value.ToString ()))
                    //{
                    if (string.IsNullOrEmpty(cell.Value.ToString().Trim()))
                    {
                        isEmpty = true;
                        break; // TODO: might not be correct. Was : Exit For
                        //  }
                    }
                }
            }
        }
        return isEmpty;
    }

you can call it by:

  if (!IsDataGridViewEmpty( dgv_absence))
        {
           MessageBox.Show("message","title");
             return;
        }