.NetFramework 2.0里提供的DataGridViewComboBoxColumn 只有在以下情况下才正常工作:它的所有单元格值(由 DataGridView.DataSource 属性填充)与选择的范围(由 DataSource 属性或 Items 属性填充)之间存在映射。如果此映射不存在,则当该列位于视图中时,会出现消息“进行格式设置时出现错误,显示”。因此,这个ComboBox无法进行自由编辑,我写了个扩展的 DataGridViewComboEditBoxColumn 类实现了ComboBoxStyle.DropDown的功能,代码的关键点为两处,一是在显示时将ComboBoxColumn以及ComboBox的Items添加入所有可能出现的项,在GetFormattedValue时实现,二是在编辑验证ComboBox数据时即时插入新项,在ComboBox.Validating时实现。
public class DataGridViewComboEditBoxCell : DataGridViewComboBoxCell
{
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
ComboBox comboBox = base.DataGridView.EditingControl as ComboBox;
if (comboBox != null)
{
comboBox.DropDownStyle = ComboBoxStyle.DropDown;
comboBox.Validating += new CancelEventHandler(comboBox_Validating);
}
}
protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
{
if (value != null)
{
if (value.ToString().Trim() != string.Empty)
{
if (Items.IndexOf(value) == -1)
{
Items.Add(value);
DataGridViewComboBoxColumn col = OwningColumn as DataGridViewComboBoxColumn;
col.Items.Add(value);
}
}
}
return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
}
void comboBox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
DataGridViewComboBoxEditingControl cbo = sender as DataGridViewComboBoxEditingControl;
if (cbo.Text.Trim() == string.Empty) return;
DataGridView grid = cbo.EditingControlDataGridView;
object value = cbo.Text;
// Add value to list if not there
if (cbo.Items.IndexOf(value) == -1)
{
DataGridViewComboBoxColumn cboCol = grid.Columns[grid.CurrentCell.ColumnIndex] as DataGridViewComboBoxColumn;
// Must add to both the current combobox as well as the template, to avoid duplicate entries
cbo.Items.Add(value);
cboCol.Items.Add(value);
grid.CurrentCell.Value = value;
}
}
}
public class DataGridViewComboEditBoxColumn : DataGridViewComboBoxColumn
{
public DataGridViewComboEditBoxColumn()
{
DataGridViewComboEditBoxCell obj = new DataGridViewComboEditBoxCell();
this.CellTemplate = obj;
}
}
{
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
ComboBox comboBox = base.DataGridView.EditingControl as ComboBox;
if (comboBox != null)
{
comboBox.DropDownStyle = ComboBoxStyle.DropDown;
comboBox.Validating += new CancelEventHandler(comboBox_Validating);
}
}
protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
{
if (value != null)
{
if (value.ToString().Trim() != string.Empty)
{
if (Items.IndexOf(value) == -1)
{
Items.Add(value);
DataGridViewComboBoxColumn col = OwningColumn as DataGridViewComboBoxColumn;
col.Items.Add(value);
}
}
}
return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
}
void comboBox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
DataGridViewComboBoxEditingControl cbo = sender as DataGridViewComboBoxEditingControl;
if (cbo.Text.Trim() == string.Empty) return;
DataGridView grid = cbo.EditingControlDataGridView;
object value = cbo.Text;
// Add value to list if not there
if (cbo.Items.IndexOf(value) == -1)
{
DataGridViewComboBoxColumn cboCol = grid.Columns[grid.CurrentCell.ColumnIndex] as DataGridViewComboBoxColumn;
// Must add to both the current combobox as well as the template, to avoid duplicate entries
cbo.Items.Add(value);
cboCol.Items.Add(value);
grid.CurrentCell.Value = value;
}
}
}
public class DataGridViewComboEditBoxColumn : DataGridViewComboBoxColumn
{
public DataGridViewComboEditBoxColumn()
{
DataGridViewComboEditBoxCell obj = new DataGridViewComboEditBoxCell();
this.CellTemplate = obj;
}
}