Farr far away....

gary farr's blog
in

January 2007 - Posts

Faking alternative controls within a DataGridView control in Win Forms 2.0

One of the limitations of the DataGridView Control within WinForms is that you can only select a few controls to place in the Grid View.  In my case I wanted to add a DateTimePicker Control within a row of the DataGridView.  I searched for example on how to do this.  Microsoft has an example of how to host controls in windows forms DataGridView cells at http://msdn2.microsoft.com/en-us/netframework/7tas5c80.aspx but I really didn’t like the fact that you had to create a column class specifically for that control.  It seemed a tremendous amount of excess code to write for a specific task.  I found a simpler way to in a sense, fake this process.  I simply created a DateTimePicker Control on the form.  I initially set the Visible property to false.  Then, upon a cell click on the DataGridView, I place the DateTimePicker control within that Cell’s limits, i.e. top, left, height, width.  The user then selects a date and as the leave the DateTimePicker control I post that result back to the particular cell.  The code below describes this process.

private void frmCategory_Load(object sender, EventArgs e)

{

this.productCategoryTableAdapter.Fill(this.dsAdventerWorks.ProductCategory);

                // Add the event handlers.

                 dgCategory.CellClick +=new DataGridViewCellEventHandler(dgCategory_CellClick);

                }

protected void dgCategory_CellClick(object sender, DataGridViewCellEventArgs e)

{

//set Date Picker to false when initially click on cell

                if (dtPicker.Visible)

                    dtPicker.Visible = false;

                if (e.ColumnIndex == 2)

                {

                    //set date picker for category datagrid

                    dtPicker.Size = dgCategory.CurrentCell.Size;

                    dtPicker.Top = dgCategory.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Top;

                    dtPicker.Left = dgCategory.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true).Left;

                    if (!(object.Equals(Convert.ToString(dgCategory.CurrentCell.Value), "")))

                        dtPicker.Value = Convert.ToDateTime(dgCategory.CurrentCell.Value);

                    dtPicker.Visible = true;

                }

}

private void dtPicker_ValueChanged(object sender, EventArgs e)

{

                 dgCategory.CurrentCell.Value = dtPicker.Value;

                 dtPicker.Visible = false;

}

                To add, I used this same methodology for a master-detail relationship between two DataGridViews.  I figured that if this can be done for any control, why not build this relation.  The only two differences are I added a handler for Leaving the second DataGridView and I put the second DataGridView along with a bound Navigator within a GroupBox control.  I did this because I wanted particular add/delete/update functionality within the second DataGridView.