4

我搜索了很多这个错误,许多相同的问题已经被问到,但它没有解决我的问题。 我得到如何将DataGridViewComboBoxCell转换为DataGridViewTextBoxCell

操作无效,因为它会导致对SetCurrentCellAddressCore函数的重入调用。

的情况是我有datagridviewTextboxColumn我使用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); 
     } 
    } 

代码是如何解决这个问题。

UPDATE: 没有行有用户将增加新的行,并选择价值,基本的事情是我想说明的组合,并填写从数据库值,填充值是视情况而定,所以每一次新的值将来,

示例数据

testTable 
1  A 
2  B 
3  C 
4  D 
5  E 
6  F 
7  G 
8  H 
9  I 

在列1我加一个组合与值从1到9,在_mFillSieveSizeGridCombo我传递id来SQL Server 2008和使用Combo.Item.Add(x)方法填充组合。

+0

奇怪。我无法复制。有多少行?第2行的值是否与其他值不同?你可以改变它到一个有效的?它是否发生在鼠标和F2上? (显然,我只是猜测 - )mFillSieveSizeGridCombo中的单元格c由于其rownumber而发生了特殊情况? – TaW 2015-03-15 21:57:04

+0

@taw没有行有用户将增加新的行,并选择值,该基地的事情是我想说明的组合,并填写从数据库值,填充值是视情况而定,所以每一次新的价值观会来, – 2015-03-16 07:31:24

+0

如果你对此有何评论'_mFillSieveSizeGridCombo'调用单元格的项目不会被填充。但错误仍然发生呢? – TaW 2015-03-16 07:36:47

回答

2

SetCurrentCellAddressCore()内有一个标志,用于防止任何可重入的呼叫破坏DataGridView的内部值。在事件结束时,美国国家队举办了一场活动,并且标志=真,并重新设置。

要解决此问题,您可以在事件内简单添加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; 
     } 
    } 
} 
+0

@Eric不能正常工作,使用当行索引== 2时,您的代码变为无限循环,并且组合未在其他行中显示,因为它已在工作。 – 2015-03-16 10:46:43

+0

@ImranAliKhan你还有其他的dgv事件吗?似乎是与别的地方冲突 – Eric 2015-03-17 01:44:21

+0

@ImranAliKhan它是由'EditOnEnter'造成的,而且你需要手动切换事件,看到我的编辑 – Eric 2015-03-17 03:24:01

2

二传手你可以从你的麻烦告诉DataGridView在实现这一点时非常不满意你试图拉地板垫。它明确禁止在关键时刻改变单元格对象。处理事件本身就是这样一个关键时刻。与事件有关的一般问题,称为重新进入。 @ Eric的方法带来的麻烦表明这确实是一个棘手的问题。

那么你所做的不是想做的就是修改单元格类型或引用。把目光放在球上,真的想要做的就是修改下拉列表的内容。这不是问题。回到设计器并将列的ColumnType属性更改为DataGridViewComboBoxColumn。并使用CellBeginEdit事件动态更改组合框项目集合。一个简单的例子:

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

这也是我的第一个想法,但原始代码在这里工作得很好,而且在OP中,除了一行中的一个单元格外。它不应该总是出现这个错误吗? – TaW 2015-03-16 13:29:11

+0

我没有尝试原始代码,但是这个例外对于他正在尝试做的事情来说是完全正常的。这取决于细胞如何进入编辑模式,有多种方式。 – 2015-03-16 13:49:26

+0

我可以F2或用鼠标做没有比其他的问题,一个有趣的feelig ;-) – TaW 2015-03-16 13:50:54

1

这里是一个解决办法:在CellBeginEdit事件首先检查,看是否ColumnTypeDataGridViewComboBoxCell。如果不是我们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代码,如果有任何..