InvalidOperationException - 结束编辑单元格时 &移动到另一个单元格 [英] InvalidOperationException - When ending editing a cell & moving to another cell
问题描述
我制作了一个程序,我想在其中手动更新数据网格视图.- 我有一种方法可以通过清除 DGV 然后重新插入数据来刷新 DGV.- 使用设计器,我为 DGV 的 CellEndEdit 制作了一个事件处理程序.在事件处理程序内部,数据得到更新 &调用DGV自定义刷新方法.
在运行程序时,每当我开始编辑单元格时通过选择另一个来结束它,抛出异常:
无效操作异常操作无效,因为它会导致对 SetCurrentCellAddressCore 函数的可重入调用.
Visual C# 的调试器标记清除数据的行:datagridview1.Rows.Clear();
如果你想重现这个问题,用visual c#新建一个windows窗体项目,在窗体上放一个DataGridView对象,在Form1.cs中粘贴以下代码:
使用系统;使用 System.Collections.Generic;使用 System.ComponentModel;使用 System.Data;使用 System.Drawing;使用 System.Linq;使用 System.Text;使用 System.Windows.Forms;命名空间错误___DataGridView_Updating___Cell_endedit{公共部分类 Form1 :表单{//对象数据表 dt;数据列 colID;数据列列名;数据列 colInfo;//构造函数公共 Form1(){初始化组件();初始化_dt();InsertSampleData_dt();Initialize_dataGridView1();}//方法私有无效 Initialize_dt(){dt = 新数据表();//构建列//IDcolID = new DataColumn();colID.ColumnName = "ID";colID.DataType = typeof(int);dt.Columns.Add(colID);//名称colName = new DataColumn();colName.ColumnName = "名称";colName.DataType = typeof(string);dt.Columns.Add(colName);//信息colInfo = new DataColumn();colInfo.ColumnName = "信息";colInfo.DataType = typeof(string);dt.Columns.Add(colInfo);}私有无效 InsertSampleData_dt(){数据行;//0行 = dt.NewRow();行[ID"] = 100;row["Name"] = "AAAA";row["Info"] = "第一条记录";dt.Rows.Add(row);//1行 = dt.NewRow();行[ID"] = 101;row["Name"] = "BBBB";row["Info"] = "第二条记录";dt.Rows.Add(row);//2行 = dt.NewRow();行[ID"] = 102;row["Name"] = "CCCC";row["信息"] = "第三条记录";dt.Rows.Add(row);}私有无效 Initialize_dataGridView1(){dataGridView1.AllowUserToAddRows = false;//数据网格定义//行标题dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;//列标题dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;//构建列#地区ID{DataGridViewColumn colSGID = new DataGridViewTextBoxColumn();colSGID.Name = "ID";colSGID.HeaderText = "#";colSGID.ReadOnly = true;colSGID.Visible = false;colSGID.Resizable = DataGridViewTriState.False;dataGridView1.Columns.Add(colSGID);}#endregion#region 名称{DataGridViewColumn colSGName = new DataGridViewTextBoxColumn();colSGName.Name = "姓名";colSGName.HeaderText = "姓名";dataGridView1.Columns.Add(colSGName);}#endregion#region 信息{DataGridViewColumn colSGSubject = new DataGridViewTextBoxColumn();colSGSubject.Name = "信息";colSGSubject.HeaderText = "说明";dataGridView1.Columns.Add(colSGSubject);}#endregionRefresh_dataGridView1();}私有无效 Refresh_dataGridView1(){整数索引;dataGridView1.SuspendLayout();dataGridView1.Rows.Clear();//MessageBox.Show("清除数据.重建...");foreach(dt.Rows 中的 DataRow 行){index = dataGridView1.Rows.Add(new DataGridViewRow());dataGridView1.Rows[index].Cells["ID"].Value = row["ID"];dataGridView1.Rows[index].Cells["Name"].Value = row["Name"];dataGridView1.Rows[index].Cells["Info"].Value = row["Info"];//MessageBox.Show("row #" + index);}dataGridView1.ResumeLayout();}//事件处理程序private void dataGridView1_CellEndEdit(对象发送者,DataGridViewCellEventArgs e){bool toUpdate = false;int id = (int)dataGridView1.Rows[e.RowIndex].Cells["ID"].Value;字符串 columnName = dataGridView1.Columns[e.ColumnIndex].Name;字符串值 = (string)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;如果(值 == 空){值 = 字符串.空;}开关(列名){案例名称":if (value == string.Empty){MessageBox.Show("名称不能为空!");}别的{toUpdate = 真;}休息;案例信息":toUpdate = 真;休息;}如果(更新){foreach(dt.Rows 中的 DataRow 行){if ( (int)row["ID"] == id){行[列名] = 值;}}Refresh_dataGridView1();}}}}
Bruce.Zhou 在 MSDN 论坛上有一个答案.我在这里发布了它的一个片段.这里也是链接到原来的帖子.
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e){………………………………………………………………………………………………………………………………………………………….;如果(更新){foreach(dt.Rows 中的 DataRow 行){if ( (int)row["ID"] == id){行[列名] = 值;}}this.BeginInvoke(new MethodInvoker(Refresh_dataGridView1));}}
<块引用>
...
When using this fix, whenever the new cell is selected, all the cells between it and the first cell (including) are selected.我正在寻找一种仅选择新单元格的方法.
I made a program in which I wanted to manually update the Data Grid View. -I have a Method to Refresh the DGV by clearing it and then reinserting the data. -Using the designer, I made an event handler for the DGV's CellEndEdit. Inside the Event Handler, the data gets updated & the DGV's custom refreshing method is called.
While running the program, whenever I start editing a cell & end it by selecting another one, an exception is thrown:
InvalidOperationException Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore function.
Visual C#'s debugger marks the line that clears the data : datagridview1.Rows.Clear();
If you'd like to reproduce the problem, Make a new windows form project with visual c#, put a DataGridView object on the form, and paste the following code for the Form1.cs:
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 Error___DataGridView_Updating___Cell_endedit
{
public partial class Form1 : Form
{
// Objects
DataTable dt;
DataColumn colID;
DataColumn colName;
DataColumn colInfo;
// Constructor
public Form1()
{
InitializeComponent();
Initialize_dt();
InsertSampleData_dt();
Initialize_dataGridView1();
}
// Methods
private void Initialize_dt()
{
dt = new DataTable();
// Building Columns
// ID
colID = new DataColumn();
colID.ColumnName = "ID";
colID.DataType = typeof(int);
dt.Columns.Add(colID);
// Name
colName = new DataColumn();
colName.ColumnName = "Name";
colName.DataType = typeof(string);
dt.Columns.Add(colName);
//Info
colInfo = new DataColumn();
colInfo.ColumnName = "Info";
colInfo.DataType = typeof(string);
dt.Columns.Add(colInfo);
}
private void InsertSampleData_dt()
{
DataRow row;
// 0
row = dt.NewRow();
row["ID"] = 100;
row["Name"] = "AAAA";
row["Info"] = "First Record";
dt.Rows.Add(row);
//1
row = dt.NewRow();
row["ID"] = 101;
row["Name"] = "BBBB";
row["Info"] = "Second Record";
dt.Rows.Add(row);
//2
row = dt.NewRow();
row["ID"] = 102;
row["Name"] = "CCCC";
row["Info"] = "Third Record";
dt.Rows.Add(row);
}
private void Initialize_dataGridView1()
{
dataGridView1.AllowUserToAddRows = false;
// Data Grid Definitions
// Row Header
dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
// ColumnHeaders
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
// Building Columns
#region ID
{
DataGridViewColumn colSGID = new DataGridViewTextBoxColumn();
colSGID.Name = "ID";
colSGID.HeaderText = "#";
colSGID.ReadOnly = true;
colSGID.Visible = false;
colSGID.Resizable = DataGridViewTriState.False;
dataGridView1.Columns.Add(colSGID);
}
#endregion
#region Name
{
DataGridViewColumn colSGName = new DataGridViewTextBoxColumn();
colSGName.Name = "Name";
colSGName.HeaderText = "Name";
dataGridView1.Columns.Add(colSGName);
}
#endregion
#region Info
{
DataGridViewColumn colSGSubject = new DataGridViewTextBoxColumn();
colSGSubject.Name = "Info";
colSGSubject.HeaderText = "Description";
dataGridView1.Columns.Add(colSGSubject);
}
#endregion
Refresh_dataGridView1();
}
private void Refresh_dataGridView1()
{
int index;
dataGridView1.SuspendLayout();
dataGridView1.Rows.Clear();
//MessageBox.Show("Cleared Data. Rebuilding...");
foreach (DataRow row in dt.Rows)
{
index = dataGridView1.Rows.Add(new DataGridViewRow());
dataGridView1.Rows[index].Cells["ID"].Value = row["ID"];
dataGridView1.Rows[index].Cells["Name"].Value = row["Name"];
dataGridView1.Rows[index].Cells["Info"].Value = row["Info"];
//MessageBox.Show("row #" + index);
}
dataGridView1.ResumeLayout();
}
//Event Handlers
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
bool toUpdate = false;
int id = (int)dataGridView1.Rows[e.RowIndex].Cells["ID"].Value;
string columnName = dataGridView1.Columns[e.ColumnIndex].Name;
string value = (string)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (value == null)
{
value = string.Empty;
}
switch (columnName)
{
case "Name":
if (value == string.Empty)
{
MessageBox.Show("Name Can't Be Empty!");
}
else
{
toUpdate = true;
}
break;
case "Info":
toUpdate = true;
break;
}
if (toUpdate)
{
foreach(DataRow row in dt.Rows)
{
if ( (int)row["ID"] == id)
{
row[columnName] = value;
}
}
Refresh_dataGridView1();
}
}
}
}
There's an answer by Bruce.Zhou at MSDN forums. I posted here a snippet from it. Here also is the link to the original post.
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
...................................................;
if (toUpdate)
{
foreach(DataRow row in dt.Rows)
{
if ( (int)row["ID"] == id)
{
row[columnName] = value;
}
}
this.BeginInvoke(new MethodInvoker(Refresh_dataGridView1));
}
}
...
When using this fix, whenever the new cell is selected, all the cells between it and the first cell (including) are selected. I am looking for a way to select only the new cell.
这篇关于InvalidOperationException - 结束编辑单元格时 &移动到另一个单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!