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.