我找了很多这个错误我得到了
操作无效,因为它会导致对SetCurrentCellAddressCore函数的重入调用。
场景是我有datagridview和TextboxColumn,我使用CellBeginEdit在ComboBoxColumn中转换它,在CellValidate之后,我再次将ComboBoxColumn更改为TextboxColumn。密码对所有人都有效。但是,在确切的行中获得所述错误,e.RowIndex = 2会抛出此异常,但其他行的剂量不会显示错误。如果省略此错误并继续,则e.RowIndex =2单元格值为空,其他行值工作。
这是CellBeginEdit的代码
if (e.ColumnIndex == 2 && e.RowIndex >= 0)
{
try
{
string s = Convert.ToString(_dgvCoarseAggegateTest[e.ColumnIndex, e.RowIndex].Value);
string s1 = Convert.ToString(_dgvCoarseAggegateTest[e.ColumnIndex, 0].Value);
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
string _SizeName = _cGetParrent._mGetParentCellValue(ref _dgvCoarseAggegateTest, e.RowIndex, 1);
_mFillSieveSizeGridCombo(_mGetMetalSizeID(_SizeName), ref c); // Here My Combo Will GetValues from SQL and it Returning Value
_dgvCoarseAggegateTest[e.ColumnIndex, e.RowIndex] = c; // Heres the error When e.RowIndex == 2 and if e.RowIndex != 2 then no error
_dgvCoarseAggegateTest[e.ColumnIndex, e.RowIndex].Value = s;
_dgvCoarseAggegateTest[e.ColumnIndex, 0].Value = s1;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}如何解决这个问题。
更新: No行用户将添加新行并选择值,基本内容是我想从数据库中显示组合式和填充值,填充值取决于条件,所以每次新值出现时,
样本数据
testTable
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I在column1中,我添加了一个值为1到9的组合体,在_mFillSieveSizeGridCombo中,我将id传递给server 2008,并使用Combo.Item.Add(x)方法填充组合框。
发布于 2015-03-16 09:12:21
SetCurrentCellAddressCore()内部有一个标志,防止任何可重入的调用破坏DataGridView的内部值。通常情况下,事件是用标志= true引发的,并在事件结束时重置。
要解决这个问题,您可以简单地在事件中添加一个BeginInvoke()包装器,以便在事件之后使用异步运行流程。
编辑
该问题可以在EditOnEnter模式下再现,而在BeginInvoke事件之外的单元格设置程序将导致不确定的循环。
private bool _suppressCellBeginEdit = false;
private void dgv_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
var dgv = sender as DataGridView;
if (_suppressCellBeginEdit)
return;
if (e.ColumnIndex == 2 && e.RowIndex >= 0)
{
string s = Convert.ToString(dgv[e.ColumnIndex, e.RowIndex].Value);
string s1 = Convert.ToString(dgv[e.ColumnIndex, 0].Value);
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
c.Items.Add(string.Format("x{0}:y{1} {2}", e.RowIndex, e.ColumnIndex, 0));
c.Items.Add(string.Format("x{0}:y{1} {2}", e.RowIndex, e.ColumnIndex, 1));
c.Items.Add(string.Format("x{0}:y{1} {2}", e.RowIndex, e.ColumnIndex, 2));
// special handling
if (e.RowIndex == e.ColumnIndex)
{
this.BeginInvoke(new Action(() =>
{
_suppressCellBeginEdit = true;
this.Invoke(new Action(() =>
{
c.Value = s;
dgv[e.ColumnIndex, e.RowIndex] = c;
dgv[e.ColumnIndex, 0].Value = s1;
}));
_suppressCellBeginEdit = false;
}));
}
else
{
c.Value = s;
dgv[e.ColumnIndex, e.RowIndex] = c;
dgv[e.ColumnIndex, 0].Value = s1;
}
}
}发布于 2015-03-16 12:52:17
正如您从实现这个问题的麻烦中可以看出的那样,DataGridView对您试图拉地板垫感到非常不高兴。它明确禁止在关键时刻更改单元对象。当它在处理一个事件时,它本身就是一个非常关键的时刻。事件的一个通用问题,叫做可重入性。您使用@Eric的方法遇到的麻烦表明,这确实是一个棘手的问题。
因此,您不想做的是修改单元格类型或引用。眼睛盯着球,你真正想做的是修改下拉列表的内容。这不是问题。返回到设计器,并将列的ColumnType属性更改为DataGridViewComboBoxColumn。并使用CellBeginEdit事件动态更改combobox项集合。一个简单的例子:
private void _dgvCoarseAggegateTest_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) {
var dgv = (DataGridView)sender;
if (e.ColumnIndex == 2) {
var cell = (DataGridViewComboBoxCell)dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
cell.Items.Clear();
// Run your dbase query here to fill cell.Items
//...
// We'll just fake it here for demo purposes:
cell.Items.Add(e.RowIndex.ToString());
cell.Items.Add((e.RowIndex+1).ToString());
cell.Items.Add((e.RowIndex+2).ToString());
}
}发布于 2015-03-16 14:41:57
这里有一个解决办法:在CellBeginEdit事件中,首先检查ColumnType是否为DataGridViewComboBoxCell。如果不是cancel事件,则调用一个更改列类型的函数,然后再次调用该事件:
void switchCellType(object sender, DataGridViewCellCancelEventArgs e)
{
DataGridViewComboBoxCell c = new DataGridViewComboBoxCell();
// prepare the cell:
//..
// fill the drop down items..
c.Items.Add("1"); // use
c.Items.Add("2"); // your
c.Items.Add("3"); // code here!
DGV[e.ColumnIndex, e.RowIndex] = c; // change the cell
DGV_CellBeginEdit(sender, e); // restart the edit with the original parms
}
private void DGV_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
DataGridViewCell cell = DGV[e.ColumnIndex, e.RowIndex];
if (!(cell is DataGridViewComboBoxCell))
{
e.Cancel = true;
switchCellType(sender, e);
return;
}
//..现在,您的代码可以继续进行,显然不会更改单元格。可能您也希望传入要设置的文本值。
注意到,您必须确保CellEndEdit事件不会在其时间之前恢复更改!!也许一面旗子,也许在Tag里会有帮助。如果你想让我看看你的CellEndEdit代码,如果有..
https://stackoverflow.com/questions/29028113
复制相似问题