Found the solution by writing a generic class derived from
DataGridTextBoxColumn with the following controls CommandBtn, ComboBox
created upfront in the constructor & based upon a enum value its going to
display the corresponding one accordingly. Here's the class which anybody
can use it.
/// <summary>
/// Derive a custom column style from DataGridTextBoxColumn
/// a) add a Command Button as a member
/// b) track when the Button has focus in Click,Enter and Leave events
/// </summary>
public delegate void DGMultiCtrlChanged( int nCurrRow, int nCurrColumn, int
nSelIndex, bool _bEditing );
public enum DGMultiColumnItems
{
e_DGTextCtrl = 0,
e_DGCmbCtrl,
e_DGCmdCtrl
}
public class DataGridMultiCtrlColumn: DataGridTextBoxColumn
{
public KeyPressCmd ColumnButton = null;
public NoKeyUpCombo ColumnComboBox = null;
private int __nRowNum = 0;
private bool _isEditing = false;
private System.Windows.Forms.CurrencyManager _source = null;
DGMultiCtrlChanged __multiCtrlEvent;
private static bool status = true;
DGMultiColumnItems __eMultiColVal = DGMultiColumnItems.e_DGTextCtrl;
public DataGridMultiCtrlColumn(DGMultiCtrlChanged _multiCtrlEvent) : base()
{
__multiCtrlEvent = _multiCtrlEvent;
ColumnButton = new KeyPressCmd();
ColumnButton.Click += new EventHandler(ButtonClick);
ColumnButton.Enter += new EventHandler(ButtonMadeCurrent);
ColumnButton.Leave += new EventHandler(ButtonLeave);
ColumnComboBox = new NoKeyUpCombo();
ColumnComboBox.Leave += new EventHandler(LeaveComboBox);
ColumnComboBox.Enter += new EventHandler(ComboMadeCurrent);
ColumnComboBox.SelectedIndexChanged +=
new System.EventHandler(ComboIndexChanged);
ColumnComboBox.SelectionChangeCommitted +=
new System.EventHandler(ComboStartEditing);
}
public DGMultiColumnItems _MultiColVal
{
get
{
return this.__eMultiColVal;
}
set
{
__eMultiColVal = value;
}
}
private void ButtonClick(object sender, EventArgs e)
{
int _nColNum = ((DataGrid)ColumnButton.Parent).CurrentCell.ColumnNumber;
__multiCtrlEvent(__nRowNum,_nColNum,0,false);
}
private void ButtonMadeCurrent(object sender, EventArgs e)
{
ColumnButton.Visible = true;
}
private void ButtonLeave(object sender, EventArgs e)
{
Invalidate();
ColumnButton.Visible = false;
}
// Combox Box private methods starts here...
private void ComboStartEditing(object sender, EventArgs e)
{
_isEditing = true;
base.ColumnStartedEditing((Control) sender);
}
private void ComboIndexChanged(object sender, EventArgs e)
{
// background data doesnt change until you leave combobox
// so we cant compare our new vs old values
int _nColNum = ((DataGrid)ColumnComboBox.Parent).CurrentCell.ColumnNumber;
int _nSelIndex = ColumnComboBox.SelectedIndex ;
__multiCtrlEvent(__nRowNum,_nColNum,_nSelIndex,false);
}
private void ComboMadeCurrent(object sender, EventArgs e)
{
//_isEditing = true;
if(status)
{
ColumnComboBox.Visible = true;
}
else
{
ColumnComboBox.Visible = false;
}
}
private void LeaveComboBox(object sender, EventArgs e)
{
if(_isEditing)
{
int _nRow, _nColumn;
_nRow = ((DataGrid)ColumnComboBox.Parent).CurrentCell.RowNumber;
_nColumn = ((DataGrid)ColumnComboBox.Parent).CurrentCell.ColumnNumber;
if (_nColumn == (int)ILineEntryType.IILE_eCC)
{
SetColumnValueAtRow(_source, _nRow, ColumnComboBox.Text);
}
else
{
if(((DataGrid)ColumnComboBox.Parent)[_nRow,0] is System.DBNull)
{ // DONT NEED AS IT IS NOW INITED WHEN ADDED USING BUTTON
}
}
_isEditing = false;
Invalidate();
}
ColumnComboBox.Hide();
}
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);
__multiCtrlEvent(rowNum,_0,0,true);
if ( (_MultiColVal == DGMultiColumnItems.e_DGCmdCtrl) ||
(_MultiColVal == DGMultiColumnItems.e_DGCmbCtrl)
)
{
__nRowNum = rowNum;
_source = source;
if (_MultiColVal == DGMultiColumnItems.e_DGCmbCtrl)
{
ColumnComboBox.Parent = this.TextBox.Parent;
ColumnComboBox.Location = this.TextBox.Location;
ColumnComboBox.Size = new Size(this.TextBox.Size.Width,
ColumnComboBox.Size.Height);
ColumnComboBox.SelectedIndexChanged -= new
System.EventHandler(ComboIndexChanged);
ColumnComboBox.Text = this.TextBox.Text;
ColumnComboBox.SelectedIndexChanged += new
System.EventHandler(ComboIndexChanged);
this.TextBox.Visible = false;
ColumnComboBox.Visible = true;
ColumnComboBox.BringToFront();
ColumnComboBox.Focus();
}
else if(_MultiColVal == DGMultiColumnItems.e_DGCmdCtrl)
{
ColumnButton.Parent = this.TextBox.Parent;
Point pt1 = TextBox.Location;
pt1.X = (pt1.X + 165);
ColumnButton.Location = pt1;//this.TextBox.Location;
Point pt2 = new Point(TextBox.Size.Width,TextBox.Size.Height);
pt2.X = pt2.X - 165;
ColumnButton.Size = new Size(pt2);//(this.TextBox.Size.Width,
TextBox.Size.Height);
ColumnButton.BackColor = System.Drawing.SystemColors.Control;
ColumnButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
ColumnButton.Text = "...";
this.TextBox.Visible = false;
ColumnButton.Visible = true;
ColumnButton.BringToFront();
ColumnButton.Focus();
}
}
else
this.TextBox.Visible = true;
}
}
public class NoKeyUpCombo : ComboBox
{
const int WM_KEYUP = 0x101;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if(m.Msg == WM_KEYUP)
{
//ignore keyup to avoid problem with tabbing & dropdownlist;
return;
}
base.WndProc(ref m);
}
} // NoKeyUpCombo
/// <summary>
/// This class is useful to handle WndProc messages generated by Command
Button control
/// </summary>
public class KeyPressCmd : Button
{
const int WM_KEYUP = 0x101;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if(m.Msg == WM_KEYUP)
{
//ignore keyup to avoid problem with tabbing & dropdownlist;
return;
}
base.WndProc(ref m);
}
} // KeyPressCmd
Thanks,
Vijai