添加行时 DataGridView 抛出“InvalidOperationException:操作无效...”

Posted

技术标签:

【中文标题】添加行时 DataGridView 抛出“InvalidOperationException:操作无效...”【英文标题】:DataGridView throwing "InvalidOperationException: Operation is not valid..." when adding a row 【发布时间】:2011-01-22 11:32:20 【问题描述】:

我希望在用户单击单元格时出现 OpenFileDialog,然后在单元格中显示结果。

一切正常,除了 DataGridView 显示一个额外的行,用于将值添加到它绑定到的列表中。如果dataGridView.AllowUserToAddNewRows == true,则显示该行,这就是我想要的。我不希望以编程方式编辑该行时应用程序崩溃;相反,它应该完全按照用户手动编辑该行的方式执行(将新行添加到基础列表,将另一个空行推送到网格以添加值)。

我阅读了有关 SendKeys.Send() 的信息,它应该使 DataGridView 的行为与用户输入的值完全相同;但是,它也不起作用。这是我正在尝试的:

if (openFileDialog1.ShowDialog() == DialogResult.OK)

    dataGridView1.CurrentCell = cell;

    //simply doing a cell.Value = etc. will cause the program to crash
    cell.ReadOnly = false;
    dataGridView1.Columns[cell.ColumnIndex].ReadOnly = false;
    dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
    dataGridView1.BeginEdit(true);
    SendKeys.Send(openFileDialog1.FileName + "Enter");
    dataGridView1.EndEdit();
    cell.ReadOnly = true;
    dataGridView1.Columns[cell.ColumnIndex].ReadOnly = true;

//I would expect the FileName would be in the cell now, and a new empty
//row tacked onto the end of the DataGridView, but it's not; the DataGridView
//is not changed at all.

【问题讨论】:

设置cell.Value时遇到什么样的异常? @Zach:当我点击空单元格时,它会正确填写值,但不会添加另一个空行。当我在该行之外单击时,最后一行上所有单元格中的值都会消失(这只发生在最后一行)。当我再次单击最后一行时,我得到一个 InvalidOperationException:“由于对象的当前状态,操作无效。” dataGridView1_CellClick 是我在该表单上处理的唯一事件(如上所示) 【参考方案1】:

我在this page 上找到了一个解决方法,但我不知道它为什么会起作用

public MyForm()

    InitializeComponent();
    //Create a BindingSource, set its DataSource to my list,
    //set the DataGrid's DataSource to the BindindingSource...
    _bindingSource.AddingNew += OnAddingNewToBindingSource;


private void OnAddingNewToBindingSource(object sender, AddingNewEventArgs e)

    if(dataGridView1.Rows.Count == _bindingSource.Count)
    
        _bindingSource.RemoveAt(_bindingSource.Count - 1);
    

我已经厌倦了花费 这么多时间 处理 Visual Studio 错误...

【讨论】:

+1 用于问答 - 谢谢,这很有效,对我们帮助很大。 +1 谢谢!几天来我一直在寻找解决方案,这成功了。 之所以起作用,是因为在 AllowUserToAddRows 为 true 的 DataGridView 上,它会在其行的末尾添加一个空行,如果绑定到列表,则会在列表的末尾创建一个空元素。您的代码删除了该元素,然后 BindingList 中的 AddNew 将触发 DataGridView 再次添加它。 事件的第一行可以是var bindingSource = (BindingSource) sender;,即不需要为此设置_bindingSource一个字段 由于某种原因,这对我没有帮助....在导致此错误的情况下,调用此事件时,gridRowCount 为 1,绑定源为 0。当实际异常发生在以下添加时,此AddingNew 事件没有机会运行并继续异常【参考方案2】:

我在尝试使用绑定源以编程方式编辑单元格时遇到了同样的问题。 ""由于对象的当前状态,操作无效"

哪个操作?什么州?很有帮助。

我的代码似乎工作正常,除了编辑网格中的最后一行。

原来关键是 DataGridView.NotifiyCurrentCelldirty(true)

以编程方式编辑单元格的正确顺序,因此它的工作方式与用户执行的操作相同。 (更改最后一行的单元格时会出现一个新的空行)是这样的:

1) 使单元格编辑当前单元格(首先对当前当前单元格执行您需要的操作 比如在编辑模式下调用 endEdit。)

2) 调用 DataGridview.BeginEdit(false)

3) 调用 DataGridView.NotifyCurrentCellDirty(true)

4) 修改值。

5) 调用 DataGridView.EndEdit()

你会想要为 RowValidating 和 RowValidated 事件做点什么。

我更新单元格值的一个例程如下所示:

这是来自我的类​​中从 DataGridView 派生的方法。 您可以从包含的表单中执行相同的操作,调用 通过 DataGridView 实例,因为方法是公共的。 这里的调用使用了一个隐含的“this”。

    private void EnterTime()
    
        if (CurrentRow == null) return;

        SaveCurrentCell(); // Calls EndEdit() if CurrentCell.IsInEditMode
        DataGridViewCell previous = CurrentCell;

        CurrentCell = CurrentRow.Cells[CatchForm.TimeColumn];
        BeginEdit(false);
        NotifyCurrentCellDirty(true);
        CurrentCell.Value = DateTime.Now;
        EndEdit();

        CurrentCell = previous;

    

我不确定为什么需要单独调用。

为什么不开始编辑,或者实际修改单元格值,导致正确 会发生什么?

如果您在实际修改单元格后将 NotifyCurrentCellDirty 调用移至, 它的行为也不正确。都很烦人。

【讨论】:

感谢您抽出宝贵时间添加此内容,达雷尔。我早就忘记了这个问题,但我会将此标记为正确,因为我不知道为什么我的解决方法有效。 就我而言,我还需要在 EndEdit() 之后调用 CurrentCell.NotifyCurrentCellDirty(false)【参考方案3】:

这是旧的,但我正在运行 VS2010,只是遇到了这个问题。我有一个DataGridView 使用BindingList<T> 绑定到List<T>。我的DataGridView 上有一个拖放事件,它会在 从 DGV 中删除所有行(除了最后一个无法删除的空白行)和 然后抛出此异常 通过BindingList<T>DragDrop 处理程序中向DGV 添加新行。如果我只是手动添加行编辑单个单元格,则不会引发此异常。

我读到的一个解决方案说要处理BindingList<T>.AddNew 事件,但我发现在DragDrop 事件处理程序中调用BindingList<T>.Add() 时此事件没有触发(我不确定为什么)。我通过添加解决了这个问题

if(bindingList.Count == 0)
    bindingList.RemoveAt(0)

DragDrop 事件处理程序内部bindingList 添加新对象之前。当bindingList 中唯一的“对象”是与最后一个空白行关联的对象时,似乎向bindingList 添加对象失败了。 BindingList<T> 的重点是允许开发人员直接使用它而不是 DGV,但这样做似乎会在边界情况下导致问题。

DGV 行和BindingList<T> 行之间的关系似乎有点灰色地带。我没有花太多时间对此进行调查,但我不清楚与 DGV 的最后(空)行关联的BindingList<T> 中的“对象”的状态是什么。但是,似乎只有在您直接与最后一行交互(而不是通过DataSource)时,才“正确”实例化最后的“对象”。

【讨论】:

太棒了。我有同样的问题。我在 drop 处理程序的开头使用了 if (DataGridView.Rows.Count == bindingList.Count) bindingList.RemoveAt(source.Count - 1); 并且有效。【参考方案4】:

试试这个:

        if (openFileDialog1.ShowDialog() == DialogResult.OK)
        
            int row = e.RowIndex;
            int clmn = e.ColumnIndex;
            if(e.RowIndex == dataGridView1.Rows.Count- 1)
                dataGridView1.Rows.Add();
            dataGridView1.Rows[row].Cells[clmn].Value = openFileDialog1.FileName;
        

编辑 我没有注意到您正在绑定您的 datagridview :( 好的,解决它:使用绑定源,将其 DataSource 属性设置为您的列表,然后将数据网格视图的数据源设置为该绑定源。现在,代码应该如下所示:

public partial class frmTestDataGridView : Form
    
        BindingSource bindingSource1 = new BindingSource();
        List<string> datasource = new List<string>();
        public frmTestDataGridView()
        
            InitializeComponent();
            datasource.Add("item1");
            datasource.Add("item2");
            datasource.Add("item3");

            bindingSource1.DataSource = datasource;
            dataGridView1.DataSource = bindingSource1;
        

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            
                int row = e.RowIndex;
                int clmn = e.ColumnIndex;

                if (e.RowIndex == dataGridView1.Rows.Count - 1)
                
                    bindingSource1.Add("");
                
                dataGridView1.Rows[row].Cells[clmn].Value = openFileDialog1.FileName;
            
        

    

【讨论】:

"当控件绑定数据时,行不能以编程方式添加到 DataGridView 的行集合中。" 如果我尝试添加到 BindingList,它会给我同样的“由于对象的当前状态,操作无效” 糟糕!我没有注意到您将 gridview 绑定到列表!我在上面更新了我的答案。请检查并告诉我们结果。 不 - 使用 BindingSource.Add() 方法可以让我在现场获得与使用 cell.Value = something 完全相同的结果(请参阅上面我对 Zach 的评论) 我找到了一个解决方法,不过还是为您的时间 +1,谢谢!【参考方案5】:

如果使用 Janus 的 DataGrid 或 GridEX(在我的例子中)连续编辑值时遇到此错误,请记住使用 Row.BeginEdit()Row.EndEdit()。 Darrel Lee 在此处发布的示例代码 (https://***.com/a/9143590/1278771) 提醒我使用这些我忘记使用的说明,这为我解决了问题。

【讨论】:

以上是关于添加行时 DataGridView 抛出“InvalidOperationException:操作无效...”的主要内容,如果未能解决你的问题,请参考以下文章

在 DataGridView 上移动行时的可视标记

C# DataGridView 数据显示到最后一行后,如何使滚动条继续向下滚动。

DataGridView DataError 未从第一行抛出

在 DataGridView 中显示数据表 SQL RealTime

如何识别 XCUITest 在 xcode 中运行时抛出的一些随机寡妇

为啥@google-cloud/profiler 在 GKE 实例中运行时会抛出“permission_denied”错误?