DataGridView Custom Column Headings

During a project at work, we found that we needed to add full text titles to the column headings in an object bound DataGridView.

We had a couple of options, but in the end settled on the one outlined here.
Email Image

We all know that it is very easy to display a collection of objects in a DataGridView, the main problem is that the column heading text is the name of the property on the corresponding object. For example, if we have a class Person with a property called Fname then the column heading will be called Fname. So how can we have the column text set to something other than the property name or an expanded text such as "Forename" or "First Name"?

Obviously we could just manually set

dataGridView.Columns["ColumnName"].HeaderText = "First Name";

However we would end up writing lots of repetitive code.

The best way I've found is to create an attribute that lists the property name and the column title.

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class DataGridColumnBindingAttribute : Attribute
{
    private string title;
    private string property;

    public DataGridColumnBindingAttribute(string title, string property)
    {
        this.title = title;
        this.property = property;
    }

    public string Title
    {
        get
        {
            return this.title;
        }
    }

    public string Property
    {
        get
        {
            return this.property;
        }
    }
}

This attribute is then applied to an enum which describes the order that the columns are added to the DataGridView.

public enum PersonColumnHeadings
{
    [DataGridColumnBindingAttribute("Title", "Title")]
    Title = 1,
    [DataGridColumnBindingAttribute("Forename", "Forename")]
    Forename = 2,
    [DataGridColumnBindingAttribute("Surname", "Surname")]
    Surname = 3,
    [DataGridColumnBindingAttribute("Date of Birth", "DOB")]
    DOB = 4
}

We then have a method that returns all the details we need to build our column headings.

public static class DataGridViewBinding
{
    public static Dictionary<string, string> GetColumnBindings(Type enumType)
    {
        Dictionary<string, string> columnTitleDescriptions = new Dictionary<string, string>();

        // Look for our string value associated with fields in this enum.
        foreach (FieldInfo fi in enumType.GetFields())
        {
            // Check for our custom attribute.
            DataGridColumnBindingAttribute[] attrs =
                fi.GetCustomAttributes(typeof(DataGridColumnBindingAttribute), false)
                as DataGridColumnBindingAttribute[];

            if (attrs.Length > 0)
            {
                columnTitleDescriptions.Add(attrs[0].Title, attrs[0].Property);
            }
        }

        return columnTitleDescriptions;
    }
}

This returns a dictionary of titles and the corresponding property.

We then need a method to build the columns given an enum with DataGridColumnBinding attributes on it.

private void CreateDataGridViewColums(DataGridView dataGridView, Type enumType)
{
    dataGridView.AutoGenerateColumns = false;
    Dictionary<string, string> columnBindings = DataGridViewBinding.GetColumnBindings(enumType);

    foreach (KeyValuePair<string, string> binding in columnBindings)
    {
        // Add the column to the DataGridView, adding the name of the column, the header text (title)
        // and the property to bind to.

        DataGridViewColumn column = dataGridView.Columns[
            dataGridView.Columns.Add(binding.Key, binding.Key)];
        column.DataPropertyName = binding.Value;
    }
}

This could be added as a static method on your own "extended" DataGridView, as an extension method or simply a utility method.

To call it, we call the method, passing it the DataGridView that we want to add the column headings to and the enum that describes the headings.

this.CreateDataGridViewColums(this.dataGridView1, typeof(PersonColumnHeadings));

The requirements for this to work are:

  1. The property in the DataGridColumnBinding must exactly match the name of the property on the class that is bound to the data grid otherwise the column will be empty.
  2. The values in the enum must be in the order that you want the columns shown (enum value 1 will be the furthest left column).

This article was published on the 3rd August 2008
Last Edited 4th August 2008