Tuesday, February 5, 2013

Embedding a Datagridview in Combobox Item

Hi,

There's a post in codeproject that will host a datagridview in a combobox. It is in vb.net and I converted it to C#. I made some changes on the custom controls to retrieve the datagridview selected row.

This was not provided in the author's post, so I made some changes myself. In total, the control was purely awesome. So, here's the C# equivalent. I won't be posting all the codes since the custom control is posted in codeproject. I'll be posting the main class instead.

Credits: Niemand25 of Lithuania
Code:
using System;  
 using System.Collections.Generic;  
 using System.ComponentModel;  
 using System.Drawing;  
 using System.Data;  
 using System.Linq;  
 using System.Text;  
 using System.Windows.Forms;  
 using System.Reflection;  
 namespace MyGridComboBoxCSharp  
 {  
   [ToolboxItem(true)]  
   [ToolboxBitmap(typeof(ComboBox))]  
   [DefaultBindingProperty("SelectedValue")]  
   [LookupBindingProperties("DataSource", "DisplayMember", "ValueMember", "SelectedValue")]  
   public partial class AccGridComboBox : ComboBox   
   {  
     private const UInt32 WM_LBUTTONDOWN = 513;    
     private const UInt32 WM_LBUTTONDBLCLK = 515;    
     private const UInt32 WM_KEYF4 = 308;    
     private ToolStripDataGridView myDataGridView = null;    
     private ToolStripDropDown myDropDown = null;    
     private object _SelectedValue = null;    
     private bool _InstantBinding = true;  
     [Browsable(false)]  
     [EditorBrowsable(EditorBrowsableState.Never)]  
     public new ComboBoxObjectCollection Items {  
       get {  
         return base.Items;  
       }  
     }  
     [Browsable(false)]  
     [EditorBrowsable(EditorBrowsableState.Never)]  
     public new object DataSource  
     {  
       get   
       {  
         return null;  
       }  
     }  
     public AccGridComboBox()   
     {  
       InitializeComponent();  
       myDropDown = new ToolStripDropDown();  
       myDropDown.AutoSize = false;  
       myDropDown.Closed += new ToolStripDropDownClosedEventHandler(this.ToolStripDropDown_Closed);  
     }  
     public bool HasAttachedGrid  
     {  
       get {  
         return !(myDataGridView == null);  
       }  
     }  
     public DataGridView AttachedGrid   
     {  
       get   
       {  
         if (!(myDataGridView == null))  
         {  
           return myDataGridView.DataGridViewControl;  
         }  
         return null;  
       }  
     }  
     protected virtual bool DisposeToolStripDataGridView   
     {  
       get   
       {  
         return true;  
       }  
     }  
     public bool InstantBinding   
     {  
       get   
       {  
         return _InstantBinding;  
       }  
       set   
       {  
         _InstantBinding = value;  
       }  
     }  
     public object SelectedValue  
     {  
       get  
       {  
         return _SelectedValue;  
       }  
       set  
       {  
         SetValue(value, true);  
         base.OnSelectedValueChanged(new EventArgs());  
       }  
     }  
     public void AddDataGridView(DataGridView nDataGridView, bool nCloseOnSingleClick)   
     {  
       if (!(myDataGridView == null))   
       {  
         throw new Exception("Error. DataGridView is already assigned to the AccGridComboBox.");  
       }  
       int count = nDataGridView.Rows.Count;  
       myDataGridView = new ToolStripDataGridView(nDataGridView, nCloseOnSingleClick);  
       myDropDown.Width = Math.Max(this.Width, myDataGridView.MinDropDownWidth);  
       myDropDown.Height = nDataGridView.Height;  
       myDropDown.Items.Clear();  
       myDropDown.Items.Add(this.myDataGridView);  
     }  
     internal void AddToolStripDataGridView(ToolStripDataGridView nToolStripDataGridView)  
     {  
       if (((nToolStripDataGridView == null) || (!(myDataGridView == null)   
             && (myDataGridView == nToolStripDataGridView))))   
       {  
         return;  
       }  
       myDataGridView = nToolStripDataGridView;  
       myDropDown.Width = Math.Max(this.Width, myDataGridView.MinDropDownWidth);  
       myDropDown.Height = myDataGridView.DropDownHeight;  
       myDropDown.Items.Clear();  
       myDropDown.Items.Add(this.myDataGridView);  
     }  
     private void ToolStripDropDown_Closed(object sender, ToolStripDropDownClosedEventArgs e) {  
       if ((e.CloseReason == ToolStripDropDownCloseReason.ItemClicked))   
       {  
         if (!base.Focused)  
         {  
           base.Focus();  
         }  
         if ((myDataGridView.DataGridViewControl.CurrentRow == null))  
         {  
           SetValue(null, false);  
         }  
         else   
         {  
           SetValue(myDataGridView.DataGridViewControl.Rows[myDataGridView.DataGridViewControl.CurrentCell.RowIndex].Cells[0].Value.ToString(), false);           
         }  
         base.OnSelectedValueChanged(new EventArgs());  
         if (_InstantBinding)  
         {  
           foreach (Binding b in base.DataBindings)   
           {  
             b.WriteValue();  
           }  
         }  
       }  
     }  
     private void SetValue(object value, bool IsValueMemberValue)   
     {  
       if ((value == null))   
       {  
         this.Text = "";  
         _SelectedValue = null;  
       }  
       else if (((this.ValueMember == null) || (string.IsNullOrEmpty(this.ValueMember.Trim()) || IsValueMemberValue)))   
       {  
         this.Text = value.ToString();  
         _SelectedValue = value;  
       }  
       else   
       {  
         object newValue = GetValueMemberValue(value);  
         if ((newValue == null))   
         {  
           this.Text = value.ToString();  
           _SelectedValue = value;  
         }  
         else {  
           this.Text = newValue.ToString();  
           _SelectedValue = newValue;  
         }  
       }  
     }  
     private Point CalculatePoz()  
     {  
       Point point = new Point(0, this.Height);  
       if (((this.PointToScreen(new Point(0, 0)).Y + (this.Height + this.myDataGridView.Height)) > Screen.PrimaryScreen.WorkingArea.Height))   
       {  
         point.Y = ((this.myDataGridView.Height - 7) * -1);  
       }  
       return point;  
     }  
     protected override void WndProc(ref Message m)  
     {  
       //base.WndProc(ref m);  
       if ((m.Msg == WM_KEYF4))  
       {  
         this.Focus();  
         this.myDropDown.Refresh();  
         if (!this.myDropDown.Visible)  
         {  
           ShowDropDown();  
         }  
         else  
         {  
           myDropDown.Close();  
         }  
         return;  
       }  
       // #End Region  
       // #Region "WM_LBUTTONDBLCLK"  
       if (((m.Msg == WM_LBUTTONDBLCLK) || (m.Msg == WM_LBUTTONDOWN)))  
       {  
         if (!this.myDropDown.Visible)  
         {  
           ShowDropDown();  
         }  
         else  
         {  
           myDropDown.Close();  
         }  
         return;  
       }  
       // #End Region  
       base.WndProc(ref m);  
     }  
     protected override void OnResize(SystemEventArgs e)   
     {  
       int minWidth = 0;  
       if (!(this.myDataGridView == null))   
       {  
         minWidth = this.myDataGridView.MinDropDownWidth;  
       }  
       myDropDown.Width = Math.Max(this.Width, minWidth);  
       if (!(myDataGridView == null))  
       {  
         myDataGridView.Width = Math.Max(this.Width, minWidth);  
         myDataGridView.DataGridViewControl.Width = Math.Max(this.Width, minWidth);  
         myDataGridView.DataGridViewControl.AutoResizeColumns();  
       }  
       base.OnResize(e);  
     }  
     protected override void OnKeyDown(System.Windows.FormsKeyEventArgs e)   
     {  
       if ((e.KeyCode == Keys.Down))   
       {  
         ShowDropDown();  
         e.Handled = true;  
       }  
       base.OnKeyDown(e);  
     }  
     private void ShowDropDown()   
     {  
       if (!(this.myDataGridView == null))   
       {  
         if (!myDropDown.Items.Contains(this.myDataGridView))   
         {  
           myDropDown.Items.Clear();  
           myDropDown.Items.Add(this.myDataGridView);  
         }  
         myDropDown.Width = Math.Max(this.Width, this.myDataGridView.MinDropDownWidth);  
         myDataGridView.Size = myDropDown.Size;  
         myDataGridView.DataGridViewControl.Size = myDropDown.Size;  
         myDataGridView.DataGridViewControl.AutoResizeColumns();  
         if ((_SelectedValue == null) || System.DBNull.Value.Equals(_SelectedValue))  
         {  
           myDataGridView.DataGridViewControl.CurrentCell = null;  
         }  
         else if ((!(this.ValueMember == null) && !string.IsNullOrEmpty(this.ValueMember.Trim())))  
         {  
           if (((myDataGridView.DataGridViewControl.Rows.Count < 1) || ((myDataGridView.DataGridViewControl.Rows[0].DataBoundItem == null)   
                 || (myDataGridView.DataGridViewControl.Rows[0].DataBoundItem.GetType().GetProperty(this.ValueMember.Trim(), (BindingFlags.Public | BindingFlags.Instance)) == null))))   
           {  
             myDataGridView.DataGridViewControl.CurrentCell = null;  
           }  
           else {  
             object CurrentValue;  
             foreach (DataGridViewRow r in myDataGridView.DataGridViewControl.Rows)  
             {  
               if (!(r.DataBoundItem == null))   
               {  
                 CurrentValue = GetValueMemberValue(r.DataBoundItem);  
                 if ((_SelectedValue == CurrentValue))   
                 {  
                   myDataGridView.DataGridViewControl.CurrentCell = myDataGridView.DataGridViewControl[0, r.Index];   
                   break;  
                 }  
               }  
             }  
           }  
         }  
         else   
         {  
           bool SelectionFound = false;  
           foreach (DataGridViewRow r in myDataGridView.DataGridViewControl.Rows) {  
             try {  
               if ((_SelectedValue == r.DataBoundItem))   
               {  
                 myDataGridView.DataGridViewControl.CurrentCell = myDataGridView.DataGridViewControl[0, r.Index];  
                 SelectionFound = true;  
                 break;  
               }  
             }  
             catch (Exception ex)   
             {  
               try   
               {  
                 if ((_SelectedValue == r.DataBoundItem))   
                 {  
                   myDataGridView.DataGridViewControl.CurrentCell = myDataGridView.DataGridViewControl[0, r.Index];  
                   SelectionFound = true;  
                   break;  
                 }  
               }  
               catch (Exception e)  
               {  
               }  
             }  
           }  
           if (!SelectionFound) {  
             myDataGridView.DataGridViewControl.CurrentCell = null;  
           }  
         }  
         myDropDown.Show(this, CalculatePoz());  
       }  
     }  
     object GetValueMemberValue(object DataboundItem) {  
       object newValue = null;  
       try   
       {  
         newValue = DataboundItem.GetType().GetProperty(this.ValueMember.Trim(), (BindingFlags.Public | BindingFlags.Instance)).GetValue(DataboundItem, null);  
       }  
       catch (Exception ex) {  
       }  
       return newValue;  
     }  
   }  
 }  
Here's the image with datagridview in combobox where no selection has been made.
And here's the image where a selection has been done in the datagrid, and the selected cell value appears in the combobox Text property.

Cheers!

1 comments:

  1. Hi This is Charitha
    Please if u have working sample using this can u send me
    charitha_sharma@yahoo.co.in

    ReplyDelete