在数据录入,数据检查或者数据监测的时候,我们通常会按照业务逻辑对传入的数据进行检查,检查出来后,怎么将错误的数据呈现出来,以什么方式呈现出来,嗯,这是个问题。有的人以不同颜色标注,但这种方式要加好几个事件,还要在事件里判断哪些是错误的等等,同时,也不好直接定位到错误的单元格上。
下面呢,我就介绍一种,不用加任何事件,直接把错误定位到单元格,同时可以添加错误信息的办法,唯一的限制条件是传入的数据必须是DataRow或DataTable的形式。(ps:以下的使用方式是我自己在实践中瞎琢磨出来的,有实践意义但不严谨,有些地方也可能不对或者有纰漏,热烈欢迎大家指正,而且,大家有没有知道System.Data.DataTable的帮助文档啥的,我可以系统的学习一下,现在都是用到啥就去网上大肆搜罗相关信息,比较耗费时间)
废话不多说,先看效果图。
上图的“不符合唯一项:规则”是可以自己定义的错误信息,可以根据需求在代码里自己定义,不过只能是string类型。
下面来介绍代码。
1.逻辑层面
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication1
{
public class HelperClass
{
public HelperClass()
{
}
public DataTable InitDataTable()
{
DataTable result = new DataTable();
Type intType = typeof(int);
Type strType = typeof(string);
Type dateType = typeof(DateTime);
Func<string, string, Type, DataColumn> createColumn = (name, caption, type) =>
{
return new DataColumn() { ColumnName = name, Caption = caption, DataType = type };
};
result.Columns.Add(createColumn("ID", "ID", intType));
result.Columns.Add(createColumn("PROJECT", "项目", strType));
result.Columns.Add(createColumn("JM", "井名", strType));
result.Columns.Add(createColumn("XGRQ", "修改日期", dateType));
DataRow row = result.NewRow();
row[0] = 1;
row[1] = "项目1";
row[2] = "井名1";
row[3] = new DateTime(1982, 4, 12);
result.Rows.Add(row);
row = result.NewRow();
row[0] = 2;
row[1] = "项目1";
row[2] = "井名1";
row[3] = DBNull.Value;
result.Rows.Add(row);
row = result.NewRow();
row[0] = 3;
row[1] = "项目2";
row[2] = "井名2";
row[3] = new DateTime(2001, 4, 12);
result.Rows.Add(row);
row = result.NewRow();
row[0] = 4;
row[1] = "项目2";
row[2] = "井名2";
row[3] = new DateTime(2001, 4, 12);
result.Rows.Add(row);
return result;
}
//假设业务逻辑是:进来的数据中,时间类型的数据都不能为空,若为空,则标注为错误
public DataTable SetErrorToDataTable(string erorrMsg, DataTable table)
{
foreach (DataColumn column in table.Columns)
{
if (column.DataType.Equals(typeof(DateTime)))
foreach (DataRow item in table.Rows)
{
if (item[column].Equals(DBNull.Value))
{
//判断之前是否设置过错误信息,若设置过,是否包含现在将设置的错误信息
//若之前设置过错误信息并不包含现在将设置的错误信息,则将新旧信息拼凑成新的错误信息设置到单元格
string preError = item.GetColumnError(column);
if (!string.IsNullOrEmpty(preError) && !preError.Contains(erorrMsg))
erorrMsg = preError + "\r\n" + erorrMsg;
item.SetColumnError(column, erorrMsg);
}
}
}
return table;
}
//假设业务逻辑是:进来的数据中,时间类型的数据不能大于目标值
public DataTable SetErrorToDataTable(string erorrMsg, DataTable table, DateTime targetTime)
{
foreach (DataColumn column in table.Columns)
{
if (column.DataType.Equals(typeof(DateTime)))
foreach (DataRow item in table.Rows)
{
if (item[column].Equals(DBNull.Value))
continue;
DateTime time = Convert.ToDateTime(item[column]);
if (time > targetTime)
{
//判断之前是否设置过错误信息,若设置过,是否包含现在将设置的错误信息
//若之前设置过错误信息并不包含现在将设置的错误信息,则将新旧信息拼凑成新的错误信息设置到单元格
string preError = item.GetColumnError(column);
if (!string.IsNullOrEmpty(preError) && !preError.Contains(erorrMsg))
erorrMsg = preError + "\r\n" + erorrMsg;
item.SetColumnError(column, erorrMsg);
}
}
}
return table;
}
//假设业务逻辑是:进来的数据中,时间类型的数据格式必须为目标格式
public DataTable SetErrorToDataTable( DataTable table, string targetFormat)
{
foreach (DataColumn column in table.Columns)
{
if (column.DataType.Equals(typeof(DateTime)))
foreach (DataRow item in table.Rows)
{
if (item[column].Equals(DBNull.Value))
continue;
DateTime time = Convert.ToDateTime(item[column]);
string timeSting = time.ToUniversalTime().ToString();
string targettString = time.ToUniversalTime().ToString(targetFormat);
if(!timeSting .Equals (targettString ))
{
string erorrMsg = string.Format("时间类型的数据格式必须为{0}", targettString); ;
string preError = item.GetColumnError(column);
if (!string.IsNullOrEmpty(preError) && !preError.Contains(erorrMsg))
erorrMsg = preError + "\r\n" + erorrMsg;
item.SetColumnError(column, erorrMsg);
}
}
}
return table;
}
public DataTable CheckDataTableDateTimeIsNull(DataTable table)
{
string errorMsg = string.Format("时间类型的数据不能为空");
table = SetErrorToDataTable(errorMsg, table);
return table;
}
public DataTable CheckDataTableDateTimeGreaterTargetDate(DataTable table, DateTime targetTime)
{
string errorMsg = string.Format("时间类型的数据不能大于目标值");
table = SetErrorToDataTable(errorMsg, table, targetTime);
return table;
}
public DataTable CheckDataTableDateTimeFormat(DataTable table, string targetFormat)
{
table = SetErrorToDataTable(table, targetFormat);
return table;
}
}
}
2.界面层面
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private HelperClass helper = new HelperClass();
public DataTable ResultTable { get; set; }
private DateTime targetTime { get; set; }
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ResultTable = helper.InitDataTable();
gridControl1.DataSource = ResultTable;
}
private void btnCheckDateIsNull_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
gridControl1.DataSource = helper.CheckDataTableDateTimeIsNull(ResultTable);
gridView1.RefreshData();
}
private void btnCheckDateValue_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
if (targetTime != null)
{
gridControl1.DataSource = helper.CheckDataTableDateTimeGreaterTargetDate(ResultTable, targetTime);
gridView1.RefreshData();
}
}
private void btnTargetDate_EditValueChanged(object sender, EventArgs e)
{
object value = btnTargetDate.EditValue;
if (value != null && value.GetType().Equals(typeof(DateTime)))
{
targetTime = Convert.ToDateTime(value);
}
}
private void btnCheckDateFormat_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
string format = "u";
gridControl1.DataSource = helper.CheckDataTableDateTimeFormat(ResultTable, format);
gridView1.RefreshData();
}
private void btnClearError_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
foreach (DataRow item in ResultTable .Rows )
{
item.ClearErrors();
}
}
}
}
注意这里string format = “u”的u代表一种时间格式https://msdn.microsoft.com/zh-cn/library/az4se3k1.aspx这个链接是标准日期和时间格式的msdn解释,有时间用的着的话可以研究一下。
下面上执行界面的图