【问题标题】:How to convert DataGridViewComboBoxCell to DataGridViewTextBoxCell如何将 DataGridViewComboBoxCell 转换为 DataGridViewTextBoxCell
【发布时间】:2015-03-13 08:50:30
【问题描述】:

我为此错误进行了很多搜索,许多相同的问题已经被问到,但它并没有解决我的问题。 我得到了

操作无效,因为它会导致对 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);
      }
    }

如何解决这个问题。

更新: 那里没有行,用户将添加新行并选择值,基本的事情是我想从数据库中显示组合和填充值,填充值取决于条件,所以每次都会出现新值,

样本数据

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

在 column1 中,我添加了一个值从 1 到 9 的组合,在 _mFillSieveSizeGridCombo 中,我将 id 传递给 sql server 2008 并使用 Combo.Item.Add(x) 方法填充组合。

【问题讨论】:

  • 奇怪。我无法重现。有多少行?第 2 行中的值与其他值有什么不同吗?你能把它改成一个有效的吗?鼠标和F2会发生这种情况吗? (显然,我只是在猜测,-) mFillSieveSizeGridCombo 中的单元格 c 由于其行号而发生了什么特殊情况?
  • @taw no row 那里用户将添加新行并选择值,基本的事情是我想从数据库中显示组合和填充值,填充值取决于条件,所以每次新值会来的,
  • 如果您评论_mFillSieveSizeGridCombo,则单元格的项目不会被填满。但是错误仍然发生吗?
  • 另外:DGV 或其数据源/绑定上是否有任何过滤器?
  • @taw DGV 没有绑定,很简单,我通过 rows.add 添加行,并且没有过滤器

标签: c# datagridview datagridviewcomboboxcell datagridviewtextboxcell


【解决方案1】:

SetCurrentCellAddressCore() 内部有一个标志,可防止任何重入调用破坏DataGridView 的内部值。通常,使用 flag = 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;
        }
    }
}

【讨论】:

  • @Eric 不工作,当行索引 ==2 时,使用您的代码进入无限循环,并且组合在其他行中未显示,因为它已经工作了。
  • @ImranAliKhan 您还处理过其他 dgv 事件吗?好像和别的地方有冲突
  • @ImranAliKhan 是EditOnEnter引起的,需要手动切换事件,看我的编辑
  • 你已经接近预期,但是当我离开单元格时,值变为空白
【解决方案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());
        }
    }

【讨论】:

  • 这也是我的第一个想法,但原始代码在这里和 OP 都可以正常工作,除了一行中的一个单元格。它不应该总是出现那个错误吗?
  • 我没有尝试原始代码,但是对于他正在尝试做的种类的事情来说,异常是完全正常的。这取决于单元格是如何进入编辑模式的,方法不止一种。
  • 我可以用 F2 或鼠标做到这一点,除了有趣的感觉之外没有任何问题 ;-)
  • 是的,dgv 上的自定义太复杂了 - 最好像您建议的那样以简单的方式使用它
  • 引用:“回到设计器并更改 ColumnType 属性”。你没有那样做。
【解决方案3】:

这里有一个解决方法:在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 代码,如果有的话..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2010-09-08
    相关资源
    最近更新 更多