datagridview 上不稳定的 InvalidOperationException
Erratic InvalidOperationException on datagridview
我的 Winform 应用程序在根级别记录 AppDomain.CurrentDomain.UnhandledException
和 Application.ThreadException,我得到了这个异常:
System.InvalidOperationException: Operation is not valid due to the current state of the object. at System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e) at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e) at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e) at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e) at System.ComponentModel.BindingList1.OnListChanged(ListChangedEventArgs e) at System.ComponentModel.BindingList
1.FireListChanged(ListChangedType type, Int32 index) at System.ComponentModel.BindingList1.InsertItem(Int32 index, T item) at System.Collections.ObjectModel.Collection
1.Add(T item) at System.ComponentModel.BindingList1.AddNewCore() at System.ComponentModel.BindingList
1.System.ComponentModel.IBindingList.AddNew() at System.Windows.Forms.CurrencyManager.AddNew() at System.Windows.Forms.DataGridView.DataGridViewDataConnection.AddNew() at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnNewRowNeeded() at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred) at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick) at System.Windows.Forms.DataGridView.ProcessDownKeyInternal(Keys keyData, Boolean& moved) at System.Windows.Forms.DataGridView.ProcessEnterKey(Keys keyData) at System.Windows.Forms.DataGridView.ProcessDialogKey(Keys keyData) at System.Windows.Forms.Control.ProcessDialogKey(Keys keyData) at System.Windows.Forms.TextBoxBase.ProcessDialogKey(Keys keyData) at System.Windows.Forms.Control.PreProcessMessage(Message& msg) at System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg) at System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)
这是 ex.ToString() 的结果,它 returns 没有我的应用程序的自定义代码,只有内部 System.Windows.Forms 方法。
有时在某些客户机器上会出现异常,我什至无法自己重现。
这味道不好,我的假设是当我更改 datagridview 的数据源边界时。但在这种情况下,我至少应该在异常堆栈中看到我的 class,但这里什么也没有。
找到根本原因或进行调试的任何线索?
非常感谢
如果调查堆栈跟踪,您会发现问题的根源:客户试图在网格上添加新记录,因此事件处理程序尝试将记录添加到数据源,这导致另一个事件处理程序,它尝试将记录添加到绑定列表,这导致事件 currencyManager_listChanged
启动,但由于对象的错误状态而失败。
要么处置列表,要么不取消订阅处置控件的事件。
我遇到了完全相同的异常,它发生在用户删除多行(启用多 select)并包括 selection 中的最后一行之后。最后一行用于添加新项目。一切正常,直到用户去编辑剩余的行,然后出现异常。
当用户不在 selection 中包含 last/add 新项目行时,删除后一切正常。
我还没有时间去调查为什么会出现这种行为,但解决方法是在多 selecting 项目时不允许包含添加新项目行,这可以被检测到通过 DataGridViewRow
的 IsNewRow
属性,然后如果此行在 selection 中,则在 DataGridView 上调用 ClearSelection()
。
private void DataGridView1_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (row.IsNewRow)
{
dataGridView1.ClearSelection();
return;
}
}
}
我的 Winform 应用程序在根级别记录 AppDomain.CurrentDomain.UnhandledException
和 Application.ThreadException,我得到了这个异常:
System.InvalidOperationException: Operation is not valid due to the current state of the object. at System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e) at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e) at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e) at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e) at System.ComponentModel.BindingList
1.OnListChanged(ListChangedEventArgs e) at System.ComponentModel.BindingList
1.FireListChanged(ListChangedType type, Int32 index) at System.ComponentModel.BindingList1.InsertItem(Int32 index, T item) at System.Collections.ObjectModel.Collection
1.Add(T item) at System.ComponentModel.BindingList1.AddNewCore() at System.ComponentModel.BindingList
1.System.ComponentModel.IBindingList.AddNew() at System.Windows.Forms.CurrencyManager.AddNew() at System.Windows.Forms.DataGridView.DataGridViewDataConnection.AddNew() at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnNewRowNeeded() at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred) at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick) at System.Windows.Forms.DataGridView.ProcessDownKeyInternal(Keys keyData, Boolean& moved) at System.Windows.Forms.DataGridView.ProcessEnterKey(Keys keyData) at System.Windows.Forms.DataGridView.ProcessDialogKey(Keys keyData) at System.Windows.Forms.Control.ProcessDialogKey(Keys keyData) at System.Windows.Forms.TextBoxBase.ProcessDialogKey(Keys keyData) at System.Windows.Forms.Control.PreProcessMessage(Message& msg) at System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg) at System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)
这是 ex.ToString() 的结果,它 returns 没有我的应用程序的自定义代码,只有内部 System.Windows.Forms 方法。
有时在某些客户机器上会出现异常,我什至无法自己重现。
这味道不好,我的假设是当我更改 datagridview 的数据源边界时。但在这种情况下,我至少应该在异常堆栈中看到我的 class,但这里什么也没有。
找到根本原因或进行调试的任何线索?
非常感谢
如果调查堆栈跟踪,您会发现问题的根源:客户试图在网格上添加新记录,因此事件处理程序尝试将记录添加到数据源,这导致另一个事件处理程序,它尝试将记录添加到绑定列表,这导致事件 currencyManager_listChanged
启动,但由于对象的错误状态而失败。
要么处置列表,要么不取消订阅处置控件的事件。
我遇到了完全相同的异常,它发生在用户删除多行(启用多 select)并包括 selection 中的最后一行之后。最后一行用于添加新项目。一切正常,直到用户去编辑剩余的行,然后出现异常。
当用户不在 selection 中包含 last/add 新项目行时,删除后一切正常。
我还没有时间去调查为什么会出现这种行为,但解决方法是在多 selecting 项目时不允许包含添加新项目行,这可以被检测到通过 DataGridViewRow
的 IsNewRow
属性,然后如果此行在 selection 中,则在 DataGridView 上调用 ClearSelection()
。
private void DataGridView1_SelectionChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
if (row.IsNewRow)
{
dataGridView1.ClearSelection();
return;
}
}
}