c# - DataGridView 绑定(bind)问题 : "Index -1 does not have a value."

标签 c# winforms data-binding datagridview .net-2.0

我有一个绑定(bind)到绑定(bind)源的数据 GridView 和表单上的几个按钮。一个按钮将项目添加到绑定(bind)源,另一个按钮删除当前选定的项目。还有一个事件处理程序监听 CurrentChanged 事件并更新 Remove 按钮的 Enabled 状态。

在我从 datagridview 中删除最后一项之前,一切都很顺利。然后我看到一个非常难看的异常:

   at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
   at System.Windows.Forms.CurrencyManager.get_Current()
   at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnRowEnter(DataGridViewCellEventArgs e)
   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.SetAndSelectCurrentCellAddress(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick, Boolean clearSelection, Boolean forceCurrentCellSelection)\r\n   at System.Windows.Forms.DataGridView.MakeFirstDisplayedCellCurrentCell(Boolean includeNewRow)
   at System.Windows.Forms.DataGridView.OnEnter(EventArgs e)
   at System.Windows.Forms.Control.NotifyEnter()
   at System.Windows.Forms.ContainerControl.UpdateFocusedControl()
   at System.Windows.Forms.ContainerControl.AssignActiveControlInternal(Control value)
   at System.Windows.Forms.ContainerControl.ActivateControlInternal(Control control, Boolean originator)
   at System.Windows.Forms.ContainerControl.SetActiveControlInternal(Control value)
   at System.Windows.Forms.ContainerControl.SetActiveControl(Control ctl)
   at System.Windows.Forms.ContainerControl.set_ActiveControl(Control value)
   at System.Windows.Forms.Control.Select(Boolean directed, Boolean forward)
   at System.Windows.Forms.Control.SelectNextControl(Control ctl, Boolean forward, Boolean tabStopOnly, Boolean nested, Boolean wrap)
   at System.Windows.Forms.Control.SelectNextControlInternal(Control ctl, Boolean forward, Boolean tabStopOnly, Boolean nested, Boolean wrap)
   at System.Windows.Forms.Control.SelectNextIfFocused()
   at System.Windows.Forms.Control.set_Enabled(Boolean value)
   at Bug3324.Form1.HandleBindingSourceCurrentChanged(Object _sender, EventArgs _e) in D:\\Dev\\TempApps\\Bug3324\\Bug3324\\Form1.cs:line 41
   at System.Windows.Forms.BindingSource.OnCurrentChanged(EventArgs e)
   at System.Windows.Forms.BindingSource.CurrencyManager_CurrentChanged(Object sender, EventArgs e)
   at System.Windows.Forms.CurrencyManager.OnCurrentChanged(EventArgs e)

我已经在一个小场景中隔离了问题:

    private BindingSource m_bindingSource = new BindingSource();

    public Form1()
    {
        InitializeComponent();

        m_bindingSource.CurrentChanged += HandleBindingSourceCurrentChanged;
        m_bindingSource.DataSource = new BindingList<StringValue>();

        dataGridView1.DataSource = m_bindingSource;

        btnAdd.Click += HandleAddClick;
        btnRemove.Click += HandleRemoveClick;
    }

    private void HandleRemoveClick(object _sender, EventArgs _e)
    {
        m_bindingSource.RemoveCurrent();
    }

    private void HandleAddClick(object _sender, EventArgs _e)
    {
        m_bindingSource.Add(new StringValue("Some string"));
    }

    private void HandleBindingSourceCurrentChanged(object _sender, EventArgs _e)
    {
        // this line throws an exception when the last item is removed from
        // the datagridview
        btnRemove.Enabled = (m_bindingSource.Current != null);

    }
}

public class StringValue
{
    public string Value { get; set; }

    public StringValue(string value)
    {
        Value = value;
    }
}

通过纯粹的实验,我发现如果我不改变 CurrentChanged 事件处理程序中的按钮状态,那么一切正常。所以我怀疑某种操作顺序问题。但是什么?为什么尝试进行与 datagridview 完全无关的更改会导致问题?

为了让事情变得更有趣,如果程序是在 VS 中启动并附加了调试器,则异常通常是无害的(或根本不显示)。但如果它自己执行,则会弹出一个包含异常详细信息的消息框。

我尝试处理 datagridview 上的 RowEnter 事件,发现在这种情况下,它仍然认为它有一行并尝试从绑定(bind)源中检索当前项,但是 m_bindingSource.Current 已经为空。为什么只有在处理 CurrentChanged 事件时才会出现此问题?

我们将不胜感激任何帮助。谢谢。

最佳答案

也许不是真正的答案,但我记得 BindingSource 和 Datagrid 在这个部门是挑剔和脆弱的。我的一般建议是不要使用 RemoveCurrent,而是从底层数据存储中删除记录。

关于c# - DataGridView 绑定(bind)问题 : "Index -1 does not have a value.",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3687820/

相关文章:

c# - 从 GridView 添加 DataRow 时如何捕获 ConstraintException?

c# - 不知道为什么我的类无法连载

wpf - 当 TextBlock 的 IsEnabled 属性更改时,如何更改超链接的颜色?

c# - 使用另一个线程修改绑定(bind)数据表时不刷新数据网格

c# - 如何使用 EWS 检索有关启用 Exchange 邮件的公用文件夹的邮件相关信息

c# - 没有为重载的模拟方法引发回调

c# - BeginExecuteReader、EndExecuteReader 和多个结果

c# - 是否可以在没有基类或接口(interface)的情况下创建动态代理?

c# - DataGridView 不显示最近插入的行

c# - 尺寸改变时宽度不改变