I want to implement a key hit with enter to dropdown a combobox that is in
the datagrid. in this case I need to override its original behaviours. I
found some codes from the web. Does anyone know how to use this code? please
help!
http://www.experts-exchange.com/Prog..._20862953.html
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Data;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
namespace AdvancedDataGrid
{
/// <summary>
/// Implementation of a ComboBox as a column in a DataGrid
/// </summary>
public class DataGridDataBoundComboBoxColumn : DataGridTextBoxColumn
{
private ComboBox internalComboBox = new ComboBox();
private bool currentlyInEdit = false;
private CurrencyManager source = null;
private int rowNum = -1;
private AdvancedDataGrid.MyDataGrid dataGrid = null;
#region Properties
private object nullValue = DBNull.Value;
/// <summary>
/// Gives a value that will be considered null and will be replaced for
showing by NullValue
/// </summary>
public object NullValue
{
set {this.nullValue = value;}
get {return this.nullValue;}
}
private object nullCorrespondingValue = null;
/// <summary>
/// Gives a value that will replace the null values (given by NullValue)
for showing
/// </summary>
public object NullCorrespondingValue
{
set {this.nullCorrespondingValue = value;}
get {return this.nullCorrespondingValue;}
}
public object DataSource
{
set
{
// If the display member or value member is wrong,
// this line will clear it
this.internalComboBox.DataSource = value;
SetComboBoxDropDownWidth();
}
get { return this.internalComboBox.DataSource; }
}
public string DisplayMember
{
set
{
this.internalComboBox.DisplayMember = value;
SetComboBoxDropDownWidth();
}
get { return this.internalComboBox.DisplayMember; }
}
public string ValueMember
{
set {this.internalComboBox.ValueMember = value; }
get { return this.internalComboBox.ValueMember; }
}
#endregion
#region Construction
public DataGridDataBoundComboBoxColumn () : base()
{
this.internalComboBox.Visible = false;
this.internalComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
// Some events that guarantee correct working
this.internalComboBox.LostFocus += new EventHandler
(OnInternalComboBoxLostFocus);
}
#endregion
#region Event handlers for the combo box
private void OnInternalComboBoxLostFocus (object sender, EventArgs e)
{
if ((sender is DataGrid && !this.internalComboBox.Focused) ||
sender == this.internalComboBox)
{
if (this.currentlyInEdit)
Commit (this.source, this.rowNum);
}
}
#endregion
#region Key management
/// <summary>
/// Handles opening and closing of the ComboBox with the keyboard
/// For this function to work, the data grid should be of type
AdvancedDataGrid
/// </summary>
/// <param name="msg"></param>
/// <param name="keyData"></param>
/// <returns></returns>
public bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (!this.currentlyInEdit)
return false;
if (keyData == Keys.Down)
{
// Try to select next or the first item
if (this.internalComboBox.SelectedIndex <
this.internalComboBox.Items.Count - 1)
this.internalComboBox.SelectedIndex++;
else if (this.internalComboBox.Items.Count > 0)
this.internalComboBox.SelectedIndex = 0;
return true;
}
else if (keyData == Keys.Up)
{
// Try to select previous or the last item
if (this.internalComboBox.SelectedIndex > 0)
this.internalComboBox.SelectedIndex--;
else if (this.internalComboBox.Items.Count > 0)
this.internalComboBox.SelectedIndex =
this.internalComboBox.Items.Count - 1;
return true;
}
else if ((keyData == (Keys.Up | Keys.Alt) ||
keyData == (Keys.Down | Keys.Alt)) &&
!this.internalComboBox.DroppedDown)
{
this.internalComboBox.DroppedDown = true;
return true;
}
// Keys.Down | Keys.Alt work automatically if DropedDown
else if ((keyData == Keys.Enter || keyData == (Keys.Up | Keys.Alt)) &&
this.internalComboBox.DroppedDown)
{
HideDropDown();
return true;
}
else if (keyData == Keys.Escape)
{
Abort (this.rowNum);
return true;
}
return false;
}
#endregion
#region Overriden methods
protected override object GetColumnValueAtRow (CurrencyManager source, int
rowNum)
{
object val = base.GetColumnValueAtRow (source, rowNum);
// Check for the null value
if (Object.Equals (val, this.NullValue) && this.NullCorrespondingValue !=
null)
val = this.NullCorrespondingValue;
foreach (object o in this.internalComboBox.Items)
{
object oVal = GetValueMember (o);
if ((oVal == null && val == null) ||
(oVal != null && oVal.Equals (val)))
return GetDisplayMember (o);
}
return DBNull.Value;
}
protected override void Abort(int rowNum)
{
// If in read only mode, just follow the basic methods
if (this.DataGridTableStyle.DataGrid.ReadOnly || this.ReadOnly ||
(this.DataGridTableStyle.DataGrid.DataSource is DataView &&
!((DataView)this.DataGridTableStyle.DataGrid.DataS ource).AllowEdit))
{
base.Abort (rowNum);
return;
}
if(this.currentlyInEdit)
{
this.currentlyInEdit = false;
this.source = null;
this.rowNum = -1;
this.internalComboBox.Hide();
if (this.internalComboBox.DroppedDown)
HideDropDown();
}
}
protected override bool Commit(CurrencyManager dataSource,int rowNum)
{
// If in read only mode, just follow the basic methods
if (this.DataGridTableStyle.DataGrid.ReadOnly || this.ReadOnly ||
(this.DataGridTableStyle.DataGrid.DataSource is DataView &&
!((DataView)this.DataGridTableStyle.DataGrid.DataS ource).AllowEdit))
return base.Commit(dataSource, rowNum);
if(this.currentlyInEdit)
{
object selValue = this.internalComboBox.SelectedValue;
if (selValue == null || Object.Equals (selValue,
this.NullCorrespondingValue))
selValue = this.NullValue;
SetColumnValueAtRow(dataSource, rowNum, selValue);
this.currentlyInEdit = false;
this.source = null;
this.rowNum = -1;
this.internalComboBox.Hide();
if (this.internalComboBox.DroppedDown)
HideDropDown();
}
return true;
}
protected override void Edit(CurrencyManager source, int rowNum, Rectangle
bounds, bool readOnly, string instantText, bool cellIsVisible)
{
// If in read only mode, just follow the basic methods
if (this.DataGridTableStyle.DataGrid.ReadOnly || this.ReadOnly ||
(this.DataGridTableStyle.DataGrid.DataSource is DataView &&
!((DataView)this.DataGridTableStyle.DataGrid.DataS ource).AllowEdit))
{
base.Edit(source, rowNum, bounds, readOnly, instantText, cellIsVisible);
return;
}
if (this.currentlyInEdit)
return;
if(!cellIsVisible)
return;
// Important: show it before setting the selected value
// otherwise in some cases the value from the previous edit is returned
// (when the drop down is open with the mouse, a new value is pointed
// and Tab is pressed)
this.internalComboBox.Bounds = bounds;
this.internalComboBox.Show();
// Get the underlying value
// The current implementation of GetColumnValueAtRow will return the
DisplayMember
object val = base.GetColumnValueAtRow (source, rowNum);
// Check for the null value
if (Object.Equals (val, this.NullValue) && this.NullCorrespondingValue !=
null)
val = this.NullCorrespondingValue;
if (val == null || val == DBNull.Value)
if (this.internalComboBox.Items.Count > 0)
this.internalComboBox.SelectedIndex = 0;
else
this.internalComboBox.SelectedIndex = -1;
else
this.internalComboBox.SelectedValue = val;
this.currentlyInEdit = true;
this.source = source;
this.rowNum = rowNum;
ColumnStartedEditing (this.internalComboBox);
}
protected override int GetMinimumHeight()
{
return this.internalComboBox.PreferredHeight + 1;
}
protected override void SetDataGridInColumn(DataGrid value)
{
base.SetDataGridInColumn (value);
if (value == this.dataGrid)
return;
Debug.Assert (value != null);
Debug.Assert (value is AdvancedDataGrid.MyDataGrid,"The used data grid
should be of type AdvancedDataGrid");
if (this.dataGrid != null)
{
this.dataGrid.Controls.Remove (this.internalComboBox);
this.dataGrid.LostFocus -= new EventHandler
(OnInternalComboBoxLostFocus);
}
this.dataGrid = (AdvancedDataGrid.MyDataGrid)value;
this.dataGrid.Controls.Add(this.internalComboBox);
// Some events that guarantee correct working
this.dataGrid.LostFocus += new EventHandler
(OnInternalComboBoxLostFocus);
}
#endregion
#region Helper functions
private void HideDropDown()
{
// Unknown why, the value is lost when DroppedDown is set to false
object val = this.internalComboBox.SelectedValue;
this.internalComboBox.DroppedDown = false;
this.internalComboBox.SelectedValue = val;
}
private object GetMember (object o, string member)
{
DataRow row = null;
if (o is DataRowView)
row = ((DataRowView)o).Row;
if (o is DataRow)
row = (DataRow)o;
if (row != null)
{
object ret = row[member];
if (ret == null)
return DBNull.Value;
else
return ret;
}
else
{
PropertyInfo pi = o.GetType().GetProperty (member);
Debug.Assert (pi != null);
return pi.GetValue (o, null);
}
}
private string GetDisplayMember (object o)
{
if (o == null || o == DBNull.Value)
return this.NullText;
object val = GetMember (o, this.internalComboBox.DisplayMember);
if (val == null || val == DBNull.Value)
return this.NullText;
else
return val.ToString();
}
private object GetValueMember (object o)
{
return GetMember (o, this.internalComboBox.ValueMember);
}
/// <summary>
/// Sets the DropDownWidth property of the combo box if all needed
/// properties are already set
/// </summary>
private void SetComboBoxDropDownWidth()
{
if (this.internalComboBox.DataSource == null ||
this.internalComboBox.DisplayMember == null ||
this.internalComboBox.DisplayMember == String.Empty)
return;
Graphics g = this.internalComboBox.CreateGraphics ();
float w = 0;
foreach (object o in this.internalComboBox.Items)
w = Math.Max (w, g.MeasureString (GetDisplayMember (o),
this.internalComboBox.Font).Width);
if (w > 0)
this.internalComboBox.DropDownWidth = (int)(w + 0.5);
}
#endregion
}
}