添加行时,DataGridView抛出“InvalidOperationException:Operation无效...”

时间:2010-03-01 21:15:19

标签: c# .net data-binding datagridview

我希望当用户点击一个单元格时出现一个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.

5 个答案:

答案 0 :(得分:16)

我在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 :(得分:10)

当尝试使用绑定源编程编辑单元格时,我遇到了同样的问题。 “”由于对象的当前状态“

,操作无效

哪个操作?什么状态?非常有帮助。

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

原来关键是DataGridView.NotifiyCurrentCelldirty(true)

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

1)让单元格编辑当前单元格(首先执行当前当前单元格所需的操作)    比如调用endEdit,如果它处于编辑模式。)

2)调用DataGridview.BeginEdit(false)

3)调用DataGridView.NotifyCurrentCellDirty(true)

4)修改价值。

5)调用DataGridView.EndEdit()

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

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

这是我从类DataGridView派生的类中的方法。 你可以从包含的表单做同样的事情,调用 通过DataGridView实例,因为方法是公共的。 这里的电话使用了一个隐含的“这个”。

    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;

    }

我不确定为什么需要单独打电话。

为什么没有BeginEdit,或实际修改单元格值,导致权利 要发生的事情?

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

答案 2 :(得分:3)

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

我读过的一个解决方案是处理BindingList<T>.AddNew事件,但我发现在BindingList<T>.Add()事件处理程序中调用DragDrop时这个事件没有触发(我不知道为什么)。我通过添加

解决了这个问题
if(bindingList.Count == 0)
    bindingList.RemoveAt(0)
DragDrop添加新对象之前,

1内的bindingList事件处理程序。当bindingList中唯一的“对象”是与最后一个空行相关联的对象时,似乎向bindingList添加对象失败了。 BindingList<T>的要点是允许开发人员直接使用代替 DGV,但似乎这样做会导致边界情况出现问题。

DGV行和BindingList<T>行之间的关系似乎有点像灰色区域。我没有花太多时间来研究这个问题,但我不清楚与DGV的最后(空)行相关联的BindingList<T>中的“对象”的状态是什么。但是,当你直接与最后一行(而不是通过DataSource)进行交互时,它看起来似乎只是“正确”实例化了“对象”。

答案 3 :(得分:1)

试试这个:

        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;
            }
        }

    }

答案 4 :(得分:0)

如果在编辑行中的值时出现此错误,请使用Row.BeginEdit()Row.EndEdit(),使用来自Janus的DataGrid或GridEX(在我的情况下)。 Darrel Lee在这里发布的示例代码(https://stackoverflow.com/a/9143590/1278771)提醒我使用我忘记使用的这些说明,这解决了我的问题。