ComboBox in DataGrid,

From: pei_world (pei_world_at_hotmail.com)
Date: 12/21/04


Date: Wed, 22 Dec 2004 02:18:34 +0800

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/Programming/Programming_Languages/C_Sharp/Q_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.DataSource).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.DataSource).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.DataSource).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
 }
}



Relevant Pages


Quantcast