【发布时间】:2011-04-10 21:51:30
【问题描述】:
我有一个绑定到绑定源的 datagridview 和一个表单上的几个按钮。一个按钮将项目添加到绑定源,另一个按钮删除当前选定的项目。还有一个事件处理程序,它侦听 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 事件,发现在这种情况下,它仍然认为它有一行并尝试从绑定源中检索当前项,但 m_bindingSource.Current 已经为空。为什么这只是处理 CurrentChanged 事件时的问题?
我们将不胜感激任何和所有的帮助。谢谢。
【问题讨论】:
-
您是否真的验证了它是 Button.Enabled 而而不是 BindSource.Current 的读数至关重要?
-
@Henk:看起来是这样。我将 Enabled 设置代码分成两行:“var currentIsNotNull = m_bindingSource.Current != null; btnRemove.Enabled = currentIsNotNull;”。然后由 btnRemove.Enabled 设置器抛出异常。也就是说,如果我根本不将 Enabled 属性的值基于绑定源,那么一切运行正常,所以它可能是 read 和 Enabled setter 的组合。
-
我试过你的代码,它似乎工作得很好。没问题,Visual Studio 调试器和直接从 .exe 也不例外。 ...
-
@pdiddy:不幸的是,这并不让我感到惊讶。这对我来说也很好用了几个月。
标签: c# winforms data-binding datagridview .net-2.0