首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将DataGridViewComboBoxCell转换为DataGridViewTextBoxCell

如何将DataGridViewComboBoxCell转换为DataGridViewTextBoxCell
EN

Stack Overflow用户
提问于 2015-03-13 08:50:30
回答 3查看 2.4K关注 0票数 4

我找了很多这个错误我得到了

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

场景是我有datagridviewTextboxColumn,我使用CellBeginEditComboBoxColumn中转换它,在CellValidate之后,我再次将ComboBoxColumn更改为TextboxColumn。密码对所有人都有效。但是,在确切的行中获得所述错误,e.RowIndex = 2会抛出此异常,但其他行的剂量不会显示错误。如果省略此错误并继续,则e.RowIndex =2单元格值为空,其他行值工作。

这是CellBeginEdit的代码

代码语言:javascript
复制
 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行用户将添加新行并选择值,基本内容是我想从数据库中显示组合式和填充值,填充值取决于条件,所以每次新值出现时,

样本数据

代码语言:javascript
复制
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)方法填充组合框。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-16 09:12:21

SetCurrentCellAddressCore()内部有一个标志,防止任何可重入的调用破坏DataGridView的内部值。通常情况下,事件是用标志= true引发的,并在事件结束时重置。

要解决这个问题,您可以简单地在事件中添加一个BeginInvoke()包装器,以便在事件之后使用异步运行流程。

编辑

该问题可以在EditOnEnter模式下再现,而在BeginInvoke事件之外的单元格设置程序将导致不确定的循环。

代码语言:javascript
复制
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;
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2015-03-16 12:52:17

正如您从实现这个问题的麻烦中可以看出的那样,DataGridView对您试图拉地板垫感到非常不高兴。它明确禁止在关键时刻更改单元对象。当它在处理一个事件时,它本身就是一个非常关键的时刻。事件的一个通用问题,叫做可重入性。您使用@Eric的方法遇到的麻烦表明,这确实是一个棘手的问题。

因此,您不想做的是修改单元格类型或引用。眼睛盯着球,你真正想做的是修改下拉列表的内容。这不是问题。返回到设计器,并将列的ColumnType属性更改为DataGridViewComboBoxColumn。并使用CellBeginEdit事件动态更改combobox项集合。一个简单的例子:

代码语言:javascript
复制
    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());
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2015-03-16 14:41:57

这里有一个解决办法:在CellBeginEdit事件中,首先检查ColumnType是否为DataGridViewComboBoxCell。如果不是cancel事件,则调用一个更改列类型的函数,然后再次调用该事件:

代码语言:javascript
复制
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代码,如果有..

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29028113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档