【问题标题】:how to validate all datagridview cells?如何验证所有 datagridview 单元格?
【发布时间】:2017-05-01 07:30:50
【问题描述】:

我有一个由一些行和列组成的 DataGridView。我想检查我的 DataGridView 的所有单元格是否有空单元格,如果任何行中的任何单元格为空,那么给我一条消息。我有一个这样做的代码,但它只检查第一行的单元格 这是我的代码:

    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
            }
        }
    }

【问题讨论】:

  • 这是一个 Windows 窗体应用程序吗?
  • 有几个验证事件。循环所有行是一种低效的检查方式
  • 是的,windows 窗体
  • 如果您不想紧贴框架的验证事件,可以使用 Fluent Validation。您也可以在单独的项目中分离验证过程。这样,您可以在另一种项目中重用它,并且不难设置实现。在这里查看我的答案stackoverflow.com/a/40997368/819153,我在那里将它用于 Asp.net 应用程序。希望这会有所帮助

标签: c# winforms validation datagridview


【解决方案1】:

如果一个单元格是否为空,您可以调用此方法返回:

 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;
    }

您可以通过以下方式调用它:

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

【讨论】:

  • 我认为这仅在 OP 在输入数据时尝试验证数据时才有用。
  • 这种方式没用,因为我想在按下表单上的按钮时验证单元格,该按钮还包含一个 datagridview。
  • 好吧,我已经用一种测试单元格是否为空的方法来编辑我的答案
  • 好的,谢谢 Beldi 的回答,您的代码在“if (!string.IsNullOrEmpty(cell.Value))”行中有错误,也在“if (!string.IsNullOrEmpty”行(Strings.Trim(cell.Value.ToString())))"
  • 很荣幸我改变了方法,试试吧,我会工作的。
【解决方案2】:

这就是我要做的。

Windows 窗体上的 DataGrid 控件可以从实现 IDataErrorInfo 的对象中读取错误

正如 MSDN 所说。

IDataErrorInfo 提供了提供用户界面可以绑定到的自定义错误信息的功能。

您在网格数据源集合中的 POCO 对象应该实现 IDataErrorInfo 让我们这样说:

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); }
    }
}

然后你可以使用一些验证技术来设置你的验证规则。

我喜欢使用DataAnnotation 来实现我的验证逻辑。

所以,假设您的班级有一个不能为空的属性(名称),您的班级可能是:

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); }
    }
}

那么如果你使用这样的验证器

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>();
    }
}

根据错误,错误将出现在每个单元格或每行的网格上。

请注意,如果您计划内联编辑您的对象,您还应该实现 INotifyPropertyChanged

这种方法的好处是将验证逻辑与用户界面分离。

【讨论】:

  • 如果你想解耦,你可以使用 Fluent Validation,在这里查看我的答案stackoverflow.com/a/40997368/819153,这样你就可以将你的验证放在一个单独的项目中。可以在任何地方使用,Windows Form、Xamarin、Asp.Net
【解决方案3】:

除了只针对每行的第一个单元格的 Cells[0] 之外,您还需要在内部 for 循环中循环遍历单元格。像这样:

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

            }
        }

【讨论】:

  • 确保您的内部循环引用该行的 Cells 集合,并且您没有尝试引用 DataGridView 的 Cells 集合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多