WinForm的DataGrid要显示ComboBox的效果必须要写一个继承自DataGridTextBoxColumn的类, 並在其中制作ComboBox的功能, 再把这个类的对象加入到DataGrid中使用即可, 做法如下:
DataGridComboBoxColumn ComboCol =new DataGridComboBoxColumn();
ComboCol.MappingName = "RegionID";
ComboCol.HeaderText = "Region";
ComboCol.Width = 120;
ComboCol.ColumnComboBox.DataSource = ds1.Tables["Region"].DefaultView;
ComboCol.ColumnComboBox.DisplayMember = "RegionDescription";
ComboCol.ColumnComboBox.ValueMember = "RegionID";
tableStyle.PreferredRowHeight = ComboCol.ColumnComboBox.Height + 2;
tableStyle.GridColumnStyles.Add(ComboCol);
dataGrid1.TableStyles.Add(tableStyle);
其中的DataGridComboBoxColumn的写法如下:
public class DataGridComboBoxColumn : DataGridTextBoxColumn
{
public NoKeyUpCombo ColumnComboBox;
private System.Windows.Forms.CurrencyManager _source;
private int _rowNum;
private bool _isEditing;
public static int _RowCount;
public DataGridComboBoxColumn() : base()
{
_source = null;
_isEditing = false;
_RowCount = -1;
ColumnComboBox = new NoKeyUpCombo();
ColumnComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
ColumnComboBox.Leave += new EventHandler(LeaveComboBox);// BS The Cheater
ColumnComboBox.SelectionChangeCommitted += new EventHandler(ComboStartEditing);
}
private void ComboStartEditing(object sender, EventArgs e)
{
_isEditing = true;
base.ColumnStartedEditing((Control) sender);
}
private void HandleScroll(object sender, EventArgs e)
{
if(ColumnComboBox.Visible)
ColumnComboBox.Hide();
}
private void LeaveComboBox(object sender, EventArgs e)
{
if(_isEditing)
{
SetColumnValueAtRow(_source, _rowNum, ColumnComboBox.Text);
_isEditing = false;
Invalidate();
}
ColumnComboBox.Hide();
this.DataGridTableStyle.DataGrid.Scroll -= new EventHandler(HandleScroll);
}
protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
{
base.Edit(source,rowNum, bounds, readOnly, instantText , cellIsVisible);
_rowNum = rowNum;
_source = source;
ColumnComboBox.Parent = this.TextBox.Parent;
ColumnComboBox.Location = this.TextBox.Location;
ColumnComboBox.Size = new Size(this.TextBox.Size.Width, ColumnComboBox.Size.Height);
ColumnComboBox.SelectedIndex = ColumnComboBox.FindStringExact(this.TextBox.Text);
ColumnComboBox.Text = this.TextBox.Text;
this.TextBox.Visible = false;
ColumnComboBox.Visible = true;
this.DataGridTableStyle.DataGrid.Scroll += new EventHandler(HandleScroll);
ColumnComboBox.BringToFront();
ColumnComboBox.Focus();
}
protected override bool Commit(System.Windows.Forms.CurrencyManager dataSource, int rowNum)
{
if(_isEditing)
{
_isEditing = false;
SetColumnValueAtRow(dataSource, rowNum, ColumnComboBox.Text);
}
return true;
}
protected override void ConcedeFocus()
{
Console.WriteLine("ConcedeFocus");
base.ConcedeFocus();
}
protected override object GetColumnValueAtRow(System.Windows.Forms.CurrencyManager source, int rowNum)
{
object s = base.GetColumnValueAtRow(source, rowNum);
DataView dv = (DataView)this.ColumnComboBox.DataSource;
int rowCount = dv.Count;
int i = 0;
while (i < rowCount)
{
if( s.Equals( dv[i][this.ColumnComboBox.ValueMember]))
break;
++i;
}
if(i < rowCount)
return dv[i][this.ColumnComboBox.DisplayMember];
return DBNull.Value;
}
protected override void SetColumnValueAtRow(System.Windows.Forms.CurrencyManager source, int rowNum, object value)
{
object s = value;
DataView dv = (DataView)this.ColumnComboBox.DataSource;
int rowCount = dv.Count;
int i = 0;
while (i < rowCount)
{
if( s.Equals( dv[i][this.ColumnComboBox.DisplayMember]))
break;
++i;
}
if(i < rowCount)
s = dv[i][this.ColumnComboBox.ValueMember];
else
s = DBNull.Value;
base.SetColumnValueAtRow(source, rowNum, s);
}
}
public class NoKeyUpCombo : ComboBox
{
private const int WM_KEYUP = 0x101;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if(m.Msg == WM_KEYUP)
{
return;
}
base.WndProc(ref m);
}
}