【问题标题】:Apply and validate a bound DataGridViewComboBoxCell directly upon selection change在选择更改时直接应用和验证绑定的 DataGridViewComboBoxCell
【发布时间】:2011-04-30 23:31:20
【问题描述】:
我有一个 Windows 窗体 DataGridView,其中包含一些使用 DataSource、DisplayMember 和 ValueMember 属性绑定到源集合的 DataGridViewComboBoxCells。目前,只有在我单击另一个单元格并且组合框单元格失去焦点后,组合框单元格才会提交更改(即引发DataGridView.CellValueChanged)。
在组合框中选择新值后,理想情况下如何直接提交更改。
【问题讨论】:
标签:
winforms
validation
datagridview
combobox
【解决方案1】:
此行为被写入DataGridViewComboBoxEditingControl 的实现中。值得庆幸的是,它可以被覆盖。首先,您必须创建上述编辑控件的子类,覆盖OnSelectedIndexChanged 方法:
protected override void OnSelectedIndexChanged(EventArgs e) {
base.OnSelectedIndexChanged(e);
EditingControlValueChanged = true;
EditingControlDataGridView.NotifyCurrentCellDirty(true);
EditingControlDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
这将确保DataGridView 在组合框中的项目选择发生更改时得到正确通知。
然后您需要继承DataGridViewComboBoxCell 并覆盖EditType 属性以从上面返回编辑控件子类(例如return typeof(MyEditingControl);)。这将确保在单元格进入编辑模式时创建正确的编辑控件。
最后,您可以将DataGridViewComboBoxColumn 的CellTemplate 属性设置为单元子类的实例(例如myDataGridViewColumn.CellTemplate = new MyCell();)。这将确保网格中的每一行都使用正确类型的单元格。
【解决方案2】:
我尝试使用Bradley's suggestion,但它对您附加单元格模板的时间很敏感。似乎我不能让设计视图连接列,我必须自己做。
相反,我使用了绑定源的 PositionChanged 事件,并由此触发了更新。这有点奇怪,因为控件仍处于编辑模式,并且数据绑定对象还没有获得选定的值。我刚刚自己更新了绑定对象。
private void bindingSource_PositionChanged(object sender, EventArgs e)
{
(MyBoundType)bindingSource.Current.MyBoundProperty =
((MyChoiceType)comboBindingSource.Current).MyChoiceProperty;
}
【解决方案3】:
我正在成功使用而不是子类化或上面有些不雅的绑定源方法来实现这一点的更好方法如下(对不起,它是 VB,但如果你不能从 VB 转换为 C#,你会遇到更大的问题 :)
Private _currentCombo As ComboBox
Private Sub grdMain_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles grdMain.EditingControlShowing
If TypeOf e.Control Is ComboBox Then
_currentCombo = CType(e.Control, ComboBox)
AddHandler _currentCombo.SelectedIndexChanged, AddressOf SelectionChangedHandler
End If
End Sub
Private Sub grdMain_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles grdMain.CellEndEdit
If Not _currentCombo Is Nothing Then
RemoveHandler _currentCombo.SelectedIndexChanged, AddressOf SelectionChangedHandler
_currentCombo = Nothing
End If
End Sub
Private Sub SelectionChangedHandler(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myCombo As ComboBox = CType(sender, ComboBox)
Dim newInd As Integer = myCombo.SelectedIndex
//do whatever you want with the new value
grdMain.NotifyCurrentCellDirty(True)
grdMain.CommitEdit(DataGridViewDataErrorContexts.Commit)
End Sub
就是这样。