首页 文章

如何将DataGridViewComboBoxCell转换为DataGridViewTextBoxCell

提问于
浏览
4

我搜索了很多这个错误很多同样的问题已被问到,但它没有解决我的问题 . 我正进入(状态

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

方案是我 datagridviewTextboxColumn 我使用 CellBeginEditComboBoxColumn 中转换它,在 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,在_1741741中我将id传递给sql server 2008并使用 Combo.Item.Add(x) 方法填充组合 .

3 回答

  • 2

    SetCurrentCellAddressCore() 中有一个标志,可防止任何重入调用损坏 DataGridView 的内部值 . Usaully引发了一个事件,其中flag = true并在事件结束时重置 .

    要解决此问题,您只需在事件中添加 BeginInvoke() 的包装,即可在事件之后使用异步运行您的进程 .

    EDIT

    该问题可以在 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;
            }
        }
    }
    
  • 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());
            }
        }
    
  • 1

    这是一个解决方法:在 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;
        }
        //..
    

    现在您的代码可以继续进行,显然没有单元格更改 . 可能你想传入文本值来设置..

    Note 您必须确保 CellEndEdit 事件在其时间之前不会还原更改!也许一面旗帜,也许在 Tag 会有所帮助 . 如果你愿意我可以查看你的 CellEndEdit 代码,如果有的话......

相关问题