Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

DataGridViewExtension

4.83/5 (32 votes)
26 May 2011CPOL7 min read 113.6K   14.4K  
An extension to the DataGridView control with functionality that I usually include manually, but encapsulated in one class.

Introduction

This project is all the bits and pieces that I have implemented in the DataGridView over the years combined into an extended DataGridView class. Included among the extra features are sub forms on rows, making an ENTER key press move to the right, CTRL + ' will copy contents from the cell above, alternating row colors without having to set the alternating row cell style, autocomplete textbox column, DateTimePicker column, and a time column.

Background

The features listed in the intro are features that I usually had to program into each individual DataGridView control that I used. Inevitably I would miss features in some grids and end users would complain. It made my life easier when I encapsulated all these features in a single class that could be utilized from the designer.

Features Detailed

Sub Forms

Sub forms in this project are made to be very similar to the way that MS Access has them but with a few extra features. Things you can do with the sub forms:

  • Show different sub forms based on the data bound item of the row
  • Specify different types of data to send to the sub form based on the data bound item of the row
  • Show multiple sub forms of different types on one row
  • Keep the sub forms stationary or mobile when horizontally scrolling the DataGridViewExtension
  • Show a sub form that contains another DataGridViewExtension so you can have infinite drill down within the DataGridViewExtension

Enter Moves Right

This feature is selectable in the designer but if enabled, whenever the user presses the Enter key, the focus shifts to the cell on the right (or first cell in the next line) not directly below. This also moves the focus to the right if the user clicks an option from an auto complete list box.

Alternating Row Colors

This is enabled by default with LightGrey as the alternating color. Both the color and enabling/disabling this feature are editable from the designer.

Copy Contents From the Cell Above

As with MS Access, if you press CRTL + ' then the contents of the cell directly above will be pasted into the current cell. This feature is always enabled.

AutoCompleteTextBoxColumn

Adding one of these to your DataGridViewExtension will allow you to select the type of auto complete you want for the cell, directly from the designer. No more having to implement the EditingControlShowing event to get your cell to have the auto complete functionality.

DateTimePickerColumn

This shows the date time picker as the editing control for cells in this column. Format and ShowUpDown are selectable from the designer.

TimeColumn

This column shows a textbox as the editing control but the value of it is a DateTime. Entering the time in this cell can be done by entering in 24 hour time, with or without colons, with or without AM/PM, or you can just use 'p' to denote PM. You can enter just hours and minutes, or hour, minutes, and seconds. Time format is editable from the designer.

E.g.: 1600, 400PM, 400 PM, 400p, 400 p, 4:00 PM, 16:00, 4:00p, 4:00pm are all valid ways to enter 4:00 PM.

081530, 81530, 8:15:30a, 8:15:30 AM, 81530a, 081530 AM, 81540am are all valid ways to enter 8:15:30 AM

Using the Code

Sub Forms

This first thing you need to do is create a class that inherits the Extensions.DataGridViewSubForm class. Only classes that inherit this base class can be set as a sub form of a DataGridViewExtension. In your class that you create, ensure you have the constructor that accepts an object and an Extensions.DataGridViewSubformCell and passes these variables to the base class. The DataGridViewExtension will always create a new instance of your sub form using this constructor. An example is shown below.

C#
public partial class ShiftSubForm : Extensions.DataGridViewSubForm
{
    public ShiftSubForm(object DataBoundItem, 
                        Extensions.DataGridViewSubformCell Cell)
           : base(DataBoundItem, Cell)
    {
        InitializeComponent();
    }

    private void ShiftSubForm_Load(object sender, EventArgs e)
    {
        employeeBindingSource.DataSource = 
         new List<SqlClasses.Data.CharterOperations.Employee>(
            new SqlClasses.Data.CharterOperations.Employee[] {
                (SqlClasses.Data.CharterOperations.Employee)this.DataBoundItem
            });
        employeeBindingSource.MoveFirst();
    }
}

The DataGridViewSubform is just an extension of the UserControl class so you can edit the sub form quite easily in the designer. In the example above, I have a binding source included in the designer. When the form loads, it converts the DataBoundItem into an Employee list and sets this as the data source for the binding source.

Once you have designed your sub form, you can then add the DataGridViewSubformColumn to your DataGridViewExtension. You need to set the column's sub form type manually somewhere in your code, like:

C#
SubFormColumn.Subform = typeof(Controls.ShiftSubForm);

You also need to set the SubformDataMember property for the column. This can be done in the designer. If you want to pass the OwningRow's data bound item, just leave this field as 'this'. You can also choose a member of the data bound item or a member of a member. For example, if I had a Shift and I wanted to pass the Employee's date of birth, then I could have SubformDataMember as Employee.DOB, but if I wanted to pass the entire employee, then SubformDataMember would be just Employee.

The other option for a DataGridViewSubformColumn is the IgnoreSubformDataBindingError field. If this is set to True then any errors while trying to retrieve the SubformDataMember from the OwningRow's data bound item will be ignored and null will be sent to the sub form. I recommend that you leave this as False while debugging. That way it will be easier to see any errors you may have made. But set it to True for release especially if you are using the member of a member method.

Image 1

Multiple Sub Forms in One Row

Including multiple DataGridViewSubformColumns in a DataGridViewExtension is perfectly fine. Whichever sub form was last shown will be the one that is placed on top. Here is the result of multiple sub forms in one DataGridViewExtension:

Image 2

Sub Form Events

There are two events that belong to the DataGridViewSubformColumn which are very handy. They are the SubformShowing and SubformClosing events. Both events have to be programmed manually somewhere in your code. During both events, you can choose to cancel the showing or closing for the sub form. During the SubformShowing event, you can set the DataGridViewExtension to show a different form and specify a different data bound item to use instead of the default SubformDataMember. An example of how to use the SubformShowing event is shown below.

C#
void SubFormColumn_SubformShowing(Extensions.DataGridViewSubformCell sender, 
                   Extensions.SubformShowingEventArgs e)
{
    if (DoNotShowSubForms)
    {
        e.Cancel = true;
        return;
    }
    if (((Employee)e.DataBoundItem).Users.Count > 0)
    {
        e.AlternateForm = typeof(Controls.ShiftSubForm2);
        e.DataBoundItem = ((Employee)e.DataBoundItem).Users.First();
    }
}

The SubformClosing event is useful if you need to check the validity of the data contained in the sub form. For example:

C#
void SubFormColumn_SubformClosing(Extensions.DataGridViewSubformCell sender, 
                   Extensions.SubformClosingEventArgs e)
{
    if (!((Employee)e.Form.DataBoundItem).IsValid())
    {
        e.Cancel = true;
        MessageBox.Show("The employee details are not correct.")
    }
}

Scrolling Sub Forms Horizontally

By default, sub forms remain stationary while you scroll left and right in the DataGridViewExtension. If you want sub forms to scroll as well, then you need to set the SubformsScrollHorizontally property of the DataGridViewExtension to true, either in code or in the designer.

Image 3

Enter Moves Right

This feature is enabled by default but to switch if off, you only need to set the EnterMovesRight property to false, either in the designer or in the code.

Image 4

Alternating Row Colors

You can implement this in the designer or in your code. It is enabled by default.

Image 5

AutoCompleteTexBox Column

Image 6

Adding one of these columns to the DataGridViewExtension enables autocomplete on the cells. If you are using a custom source, you can specify the options in the 'Edit Columns' control or programmatically in your code. An example is shown below of how to do it in your code.

C#
Extensions.DataGridViewAutoCompleteTextboxColumn col =
    (Extensions.DataGridViewAutoCompleteTextboxColumn)
     dataGridViewExtension1.Columns[0];
col.AutoCompleteCollection.AddRange(new string[] {
                "Test 1""Test 2""Test 3"
            });
for (int i = 0; i < 10; i++)
    col.AutoCompleteCollection.Add(i.ToString());

DateTimePicker Column

Using this type of column in your DataGridViewExtension will enable the DateTimePicker to be the editing control for the cell. The only properties that you have to set in the designer are the format for the control, whether to show the up down instead of the calendar, and the custom format if you choose this format.

Image 7

TimeColumn

To use this column in your project, the only property that you have to set is the format. You can only use time format strings for this column (i.e.: h, H, m, s, t, hh, HH, mm, ss, tt and :).

Image 8

History

  • 11 May 2011 - Original version posted.
  • 17 May 2011 - Fixed positioning bugs and added demo project.
  • 20 May 2011 - Fixed bug where subform would be removed if the owning row's DataBoundItem implements INotifyPropertyChanged and this DataBoundItem was being edited in the sub form.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)