• DataGridView中数据输入验证


    把一个DataTable或者某个object集合的数据源绑定到DataGridView中,直接通过DataGridView数据录入需要进行额外的数据验证。数据验证总共分成两个大类:

    I)类型验证:

    所谓“类型验证”,就是输入的数据是不是可以(有效)转化成特定的类型(比如字段是int,但是输入确实abc等),这明显不符合要求。默认情况下,直接在绑定的DataGridView输入不符合类型的数据,当切换到下一条信息或者调用EndEdit方法将抛出异常。这很难看,我们可以通过处理DataError来实现强制性输入正确类型,代码非常简单:

    [C#]

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            DataTable dt = new DataTable();
            DataGridView dv = new DataGridView();
    
            public Form1()
            {
                InitializeComponent();
                dt.Columns.Add("Id", typeof(int));
                dt.Columns.Add("Name", typeof(string));
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                for (int i = 1; i < 11; i++)
                {
                    dt.Rows.Add(i, "Name" + i);
                }
                dt.AcceptChanges();
                dv.Parent = this;
                dv.Dock = DockStyle.Fill;
                dv.DataSource = dt;
    
                //自定义出错事件处理,到DataError这边处理
                dv.DataError += new DataGridViewDataErrorEventHandler(dv_DataError);
            }
            void dv_DataError(object sender, DataGridViewDataErrorEventArgs e)
            {
                e.ThrowException = false;
            }
        }
    }

    [VB.NET]

    Namespace WinFormCSharp
        Public Partial Class Form1
            Inherits Form
            Private dt As New DataTable()
            Private dv As New DataGridView()
    
            Public Sub New()
                InitializeComponent()
                dt.Columns.Add("Id", GetType(Integer))
                dt.Columns.Add("Name", GetType(String))
            End Sub
    
            Private Sub Form1_Load(sender As Object, e As EventArgs)
                For i As Integer = 1 To 10
                    dt.Rows.Add(i, "Name" & i)
                Next
                dt.AcceptChanges()
                dv.Parent = Me
                dv.Dock = DockStyle.Fill
                dv.DataSource = dt
    
                '自定义出错事件处理,到DataError这边处理
                dv.DataError += New DataGridViewDataErrorEventHandler(AddressOf dv_DataError)
            End Sub
    
            Private Sub dv_DataError(sender As Object, e As DataGridViewDataErrorEventArgs)
                e.ThrowException = False
            End Sub
        End Class
    End Namespace

    注意:DataError事件通常在调用EndEdit(DataGridView编辑完一行,开始下一行默认调用此事件)之后被触发,此时如果输入数据无法转换到列需要的那个类型就会触发DataError事件。因此你处理这个事件(通过把ThrowException=false)之后,异常框不会弹出,而是光标永久定格在那个单元格中(其余操作都无法做),直到你改变了数据符合规定的类型为止

    II)自定义验证:

    所谓“自定义验证”就是说录入数据在完全符合类型转换的条件下检查一些数据类型的范围。我们仍旧拿上面的举例子——假设规定Id范围只能在1~100之间,如何处理呢?

    你可以处理CellValidating事件。该事件可以通过一个e.FormattedValue获取当前单元格内容,以便你对其进行操作。现在我们先假定排除第I种错误,纯粹是第二种,那么你应该在原来的基础上添加如下粗体部分的代码(Button是模拟保存数据到内存数据表中,顺便用于测试范围验证是否成功):

    [C#]

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            DataTable dt = new DataTable();
            DataGridView dv = new DataGridView();
            Button btn = new Button();
       
            public Form1()
            {
                InitializeComponent();
                dt.Columns.Add("Id", typeof(int));
                dt.Columns.Add("Name", typeof(string));
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                for (int i = 1; i < 11; i++)
                {
                    dt.Rows.Add(i, "Name" + i);
                }
                dt.AcceptChanges();
                dv.Parent = this;
                dv.Dock = DockStyle.Fill;
                dv.DataSource = dt;
                //添加一个保存到DataTable中的按钮
                btn.Parent = this;
                btn.Dock = DockStyle.Bottom;
                btn.Text = "Save To DataTable";
                //当不满足条件,该字段为错误
                dv.ShowCellErrors = true;
                //处理单元格验证事件
                dv.CellValidating += dv_CellValidating;
                //处理按钮事件
                btn.Click += new EventHandler(btn_Click);
            }
    
            void btn_Click(object sender, EventArgs e)
            {
               
                bool flag=true; //默认没有错误
    
                //循环遍历检测是否有错误
                dv.Rows.Cast<DataGridViewRow>().ToList().ForEach(row=>{
                    if(row.Cells[0].ErrorText!="")
                    {
                        flag=false; //有错误
                    }
                }
                    );
    
                if (flag)
                {
                    dt.AcceptChanges();
                }
                else
                {
                    MessageBox.Show("注意,你的单元格中仍旧有错误!");
                }
            }
    
            void dv_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
            {
                //如果是第一个字段
                if (e.ColumnIndex == 0)
                {
                    //先转化成int类型
                    int n = int.Parse(e.FormattedValue.ToString());
    
                    //范围判断
                    if (n < 1 || n > 100)
                    {
                        dv.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "必须在1~100之内!";
                    }
                    else
                    {
                        dv.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
                    }
                }
            }
    
            void dv_DataError(object sender, DataGridViewDataErrorEventArgs e)
            {
                e.ThrowException = false;
            }
        }
    }

    [VB.NET]

    Namespace WinFormCSharp
        Public Partial Class Form1
            Inherits Form
            Private dt As New DataTable()
            Private dv As New DataGridView()
            Private btn As New Button()
    
            Public Sub New()
                InitializeComponent()
                dt.Columns.Add("Id", GetType(Integer))
                dt.Columns.Add("Name", GetType(String))
            End Sub
    
            Private Sub Form1_Load(sender As Object, e As EventArgs)
                For i As Integer = 1 To 10
                    dt.Rows.Add(i, "Name" & i)
                Next
                dt.AcceptChanges()
                dv.Parent = Me
                dv.Dock = DockStyle.Fill
                dv.DataSource = dt
                '添加一个保存到DataTable中的按钮
                btn.Parent = Me
                btn.Dock = DockStyle.Bottom
                btn.Text = "Save To DataTable"
                '当不满足条件,该字段为错误
                dv.ShowCellErrors = True
                '处理单元格验证事件
                AddHandler dv.CellValidating, AddressOf dv_CellValidating
                '处理按钮事件
                AddHandler btn.Click, AddressOf btn_Click
            End Sub
    
            Private Sub btn_Click(sender As Object, e As EventArgs)
    
                Dim flag As Boolean = True
                '默认没有错误
                '循环遍历检测是否有错误
                dv.Rows.Cast(Of DataGridViewRow)().ToList().ForEach(Function(row) 
                If row.Cells(0).ErrorText <> "" Then
                        '有错误
                    flag = False
                End If
    
    End Function)
    
                If flag Then
                    dt.AcceptChanges()
                Else
                    MessageBox.Show("注意,你的单元格中仍旧有错误!")
                End If
            End Sub
    
            Private Sub dv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs)
                '如果是第一个字段
                If e.ColumnIndex = 0 Then
                    '先转化成int类型
                    Dim n As Integer = Integer.Parse(e.FormattedValue.ToString())
    
                    '范围判断
                    If n < 1 OrElse n > 100 Then
                        dv.Rows(e.RowIndex).Cells(e.ColumnIndex).ErrorText = "必须在1~100之内!"
                    Else
                        dv.Rows(e.RowIndex).Cells(e.ColumnIndex).ErrorText = ""
                    End If
                End If
            End Sub
    
            Private Sub dv_DataError(sender As Object, e As DataGridViewDataErrorEventArgs)
                e.ThrowException = False
            End Sub
        End Class
    End Namespace

    由于DataGridView似乎没有公共的方法或属性直接判断有没有错误的单元格,所以按钮事件用扩展方法循环遍历每个行的第一列字段。

    这样,类型和有效性验证都做到了!

    不过我们可以精简代码(只用CellValidating事件一次性完成,因为该事件优先于DataError发生),通过设置其Cancel属性可以控制该事件是否被取消(“取消”会让光标定格在本单元格内,无法处理其它事情)。

    [C#]

    namespace WinFormCSharp
    {
        public partial class Form1 : Form
        {
            DataTable dt = new DataTable();
            DataGridView dv = new DataGridView();
            Button btn = new Button();
       
            public Form1()
            {
                InitializeComponent();
                dt.Columns.Add("Id", typeof(int));
                dt.Columns.Add("Name", typeof(string));
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                for (int i = 1; i < 11; i++)
                {
                    dt.Rows.Add(i, "Name" + i);
                }
                dt.AcceptChanges();
                dv.Parent = this;
                dv.Dock = DockStyle.Fill;
                dv.DataSource = dt;
                //添加一个保存到DataTable中的按钮
                btn.Parent = this;
                btn.Dock = DockStyle.Bottom;
                btn.Text = "Save To DataTable";
                //当不满足条件,该字段为错误
                dv.ShowCellErrors = true;
                //处理单元格验证事件
                dv.CellValidating += dv_CellValidating;
            }
    
            void btn_Click(object sender, EventArgs e)
            {
               
                bool flag=true; //默认没有错误
    
                //循环遍历检测是否有错误
                dv.Rows.Cast<DataGridViewRow>().ToList().ForEach(row=>{
                    if(row.Cells[0].ErrorText!="")
                    {
                        flag=false; //有错误
                    }
                }
                    );
    
                if (flag)
                {
                    dt.AcceptChanges();
                }
                else
                {
                    MessageBox.Show("注意,你的单元格中仍旧有错误!");
                }
            }
    
            void dv_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
            {
                //如果是第一个字段
                if (e.ColumnIndex == 0)
                {
                    
                    int n = 0;
    
                    //先转化成int类型,尝试转化
                    if (int.TryParse(e.FormattedValue.ToString(), out n))
                    {
                        //可以的话,再进一步范围判断
                        if (n < 1 || n > 100)
                        {
                            dv.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "必须在1~100之内!";
                        }
                        else
                        {
                            dv.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
                        }
                    }
                    else
                    {
                        //转换失败,类型都有问题
                        e.Cancel = true;
                    }
                }
            }
        }
    }

    [VB.NET]

    Namespace WinFormCSharp
        Public Partial Class Form1
            Inherits Form
            Private dt As New DataTable()
            Private dv As New DataGridView()
            Private btn As New Button()
    
            Public Sub New()
                InitializeComponent()
                dt.Columns.Add("Id", GetType(Integer))
                dt.Columns.Add("Name", GetType(String))
            End Sub
    
            Private Sub Form1_Load(sender As Object, e As EventArgs)
                For i As Integer = 1 To 10
                    dt.Rows.Add(i, "Name" & i)
                Next
                dt.AcceptChanges()
                dv.Parent = Me
                dv.Dock = DockStyle.Fill
                dv.DataSource = dt
                '添加一个保存到DataTable中的按钮
                btn.Parent = Me
                btn.Dock = DockStyle.Bottom
                btn.Text = "Save To DataTable"
                '当不满足条件,该字段为错误
                dv.ShowCellErrors = True
                '处理单元格验证事件
                AddHandler dv.CellValidating, AddressOf dv_CellValidating
            End Sub
    
            Private Sub btn_Click(sender As Object, e As EventArgs)
    
                Dim flag As Boolean = True
                '默认没有错误
                '循环遍历检测是否有错误
                dv.Rows.Cast(Of DataGridViewRow)().ToList().ForEach(Function(row) 
                If row.Cells(0).ErrorText <> "" Then
                        '有错误
                    flag = False
                End If
    
    End Function)
    
                If flag Then
                    dt.AcceptChanges()
                Else
                    MessageBox.Show("注意,你的单元格中仍旧有错误!")
                End If
            End Sub
    
            Private Sub dv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs)
                '如果是第一个字段
                If e.ColumnIndex = 0 Then
    
                    Dim n As Integer = 0
    
                    '先转化成int类型,尝试转化
                    If Integer.TryParse(e.FormattedValue.ToString(), n) Then
                        '可以的话,再进一步范围判断
                        If n < 1 OrElse n > 100 Then
                            dv.Rows(e.RowIndex).Cells(e.ColumnIndex).ErrorText = "必须在1~100之内!"
                        Else
                            dv.Rows(e.RowIndex).Cells(e.ColumnIndex).ErrorText = ""
                        End If
                    Else
                        '转换失败,类型都有问题
                        e.Cancel = True
                    End If
                End If
            End Sub
        End Class
    End Namespace
  • 相关阅读:
    [LeetCode] 1218. Longest Arithmetic Subsequence of Given Difference 最长定差子序列
    [LeetCode] 1217. Minimum Cost to Move Chips to The Same Position 玩筹码
    [LeetCode] 1209. Remove All Adjacent Duplicates in String II 移除字符串中所有相邻的重复字符之二
    [.Net Core] Visual Studio for Mac Add Client Side Library
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
    一手遮天 Android
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2440813.html
Copyright © 2020-2023  润新知