27

Does C# allow you to add a String to a RowHeader in a DataGridView? If so, how is it accomplished?

I'm writing a Windows Form to displayed Customer Payment Data for the year so far.

The ColumnHeaders display January, February, March, etc... and rather than have a blank column with DateTime.Now.Year I would like to put it in the RowHeader to make it stand out from the actual payment data.

Zach Johnson
  • 23,678
  • 6
  • 69
  • 86
Bailz
  • 605
  • 2
  • 8
  • 17
  • Can you give me detail on what you are trying to achieve here. Context will help immensely in getting a response. – Lazarus Apr 02 '09 at 15:02
  • I'm aiming to display data about a Customers payments across the year. My Column Headers display January, February, Mar... I would like to place the year in the row header on the left so that it stands out from Paid, Unpaid and Unbilled in the normal Table Cells to in the main table. – Bailz Apr 03 '09 at 08:34

13 Answers13

31
private void dtgworkingdays_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
    this.FillRecordNo();
}


private void FillRecordNo()
{
    for (int i = 0; i < this.dtworkingdays.Rows.Count; i++)
    {
        this.dtgworkingdays.Rows[i].HeaderCell.Value = (i + 1).ToString();
    }
}

Also see Show row number in row header of a DataGridView.

imsome1
  • 1,182
  • 4
  • 22
  • 37
Moon
  • 311
  • 3
  • 2
  • Nice generic solution. Casting the sender to a datagridview and using that instead of dtworkingdays makes it even more generic. – buckley Oct 13 '11 at 09:32
  • I think this is the best solution when using binding data. The other methods didn't work for me. – Mark Lakata Jul 12 '12 at 03:36
22
datagridview1.Rows[0].HeaderCell.Value = "Your text";

It works.

Appulus
  • 18,630
  • 11
  • 38
  • 46
Monali
  • 221
  • 2
  • 2
9

You don't have to use the RowValidated event, that's just the one I used for a little test app to make sure this worked, but this will set the row (not column) header text to whatever year you specify.

It would probably go better in the CellFormatting event, actually.

    private void dataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)
    {
        DataGridView gridView = sender as DataGridView;

        if (null != gridView)
        {
            gridView.Rows[e.RowIndex].HeaderCell.Value = "2009";
        }
    }

EDIT: Here's the entire TestForm I used, as simple as possible to demonstrate the solution. Make sure your RowHeadersWidth is wide enough to display the text.

#region

using System.ComponentModel;
using System.Windows.Forms;

#endregion

namespace DataGridViewTest
{
    public class GridTest : Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private IContainer components;

        private DataGridView dataGridView1;
        private DataGridViewTextBoxColumn Month;

        public GridTest()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void dataGridView_RowValidated(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView gridView = sender as DataGridView;

            if (null != gridView)
            {
                gridView.Rows[e.RowIndex].HeaderCell.Value = "2009";
            }
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.Month = new System.Windows.Forms.DataGridViewTextBoxColumn();
            ((System.ComponentModel.ISupportInitialize) (this.dataGridView1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
            this.dataGridView1.ColumnHeadersHeightSizeMode =
                System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[]
                                                    {
                                                        this.Month
                                                    });
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 0);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.RowHeadersWidth = 100;
            this.dataGridView1.Size = new System.Drawing.Size(745, 532);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.RowValidated +=
                new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_RowValidated);
            // 
            // Month
            // 
            this.Month.HeaderText = "Month";
            this.Month.Name = "Month";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(745, 532);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize) (this.dataGridView1)).EndInit();
            this.ResumeLayout(false);
        }

        #endregion
    }
}
Chris Doggett
  • 19,959
  • 4
  • 61
  • 86
5

it's because of your first column (Rows Header column) width ! increase it's width then you can see it's value ! you can use this command:

dgv1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;

(notice: you must first set dgv1.RowHeadersVisible = true;)

Majid
  • 3,128
  • 1
  • 26
  • 31
3

I had the same problem, but I noticed that my datagrid lost the rows's header after the datagrid.visible property changed.

Try to update the rows's headers with the Datagrid.visiblechanged event.

Appulus
  • 18,630
  • 11
  • 38
  • 46
robson
  • 31
  • 1
2

I had the same(?) problem. Couldn't get header column to display row header data (a simple row number) with my data bound grid. Once I moved the code to the event "DataBindingComplete" it worked.

Sorry for the extra code. I wanted to provide a working example but don't have time to cut it all down so just cut and pasted some of my app and fixed it up to run for you. Here you go:

using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        private List<DataPoint> pts = new List<DataPoint>();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            InsertPoint(10, 20);
            InsertPoint(12, 40);
            InsertPoint(16, 60);
            InsertPoint(20, 77);
            InsertPoint(92, 80);

            MakeGrid();
        }

        public void InsertPoint(int parameterValue, int commandValue)
        {
            DataPoint pt = new DataPoint();
            pt.XValue = commandValue;
            pt.YValues[0] = parameterValue;
            pts.Add(pt);
        }

        private void MakeGrid()
        {
            dgv1.SuspendLayout();
            DataTable dt = new DataTable();
            dt.Columns.Clear();
            dt.Columns.Add("Parameter");
            dt.Columns.Add("Command");

            //*** Add Data to DataTable
            for (int i = 0; i <= pts.Count - 1; i++)
            {
                dt.Rows.Add(pts[i].XValue, pts[i].YValues[0]);
            }
            dgv1.DataSource = dt;

            //*** Formatting for the grid is performed in event dgv1_DataBindingComplete.
            //*** If its performed here, the changes appear to get wiped in the grid control.
        }

        private void dgv1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            DataGridViewCellStyle style = new DataGridViewCellStyle();
            style.Alignment = DataGridViewContentAlignment.MiddleRight;

            //*** Add row number to each row
            foreach (DataGridViewRow row in dgv1.Rows)
            {
                row.HeaderCell.Value = (row.Index + 1).ToString();
                row.HeaderCell.Style = style;
                row.Resizable = DataGridViewTriState.False;
            }
            dgv1.ClearSelection();
            dgv1.CurrentCell = null;
            dgv1.ResumeLayout();
        }
    }
}
Baraticus
  • 21
  • 1
2

yes you can

DataGridView1.Rows[0].HeaderCell.Value = "my text";
ma7moud
  • 423
  • 1
  • 4
  • 8
1
foreach (DataGridViewRow row in datagrid.Rows)
                        row.HeaderCell.Value = String.Format("{0}", row.Index + 1);
MBahamondes
  • 360
  • 1
  • 2
  • 9
1

I think it should be:

dataGridView1.Columns[0].HeaderCell.Value = "my text";
Navya
  • 35
  • 2
  • 9
0

Here's a little "coup de pouce"

Public Class DataGridViewRHEx
Inherits DataGridView

Protected Overrides Function CreateRowsInstance() As System.Windows.Forms.DataGridViewRowCollection
    Dim dgvRowCollec As DataGridViewRowCollection = MyBase.CreateRowsInstance()
    AddHandler dgvRowCollec.CollectionChanged, AddressOf dvgRCChanged
    Return dgvRowCollec
End Function

Private Sub dvgRCChanged(sender As Object, e As System.ComponentModel.CollectionChangeEventArgs)
    If e.Action = System.ComponentModel.CollectionChangeAction.Add Then
        Dim dgvRow As DataGridViewRow = e.Element
        dgvRow.DefaultHeaderCellType = GetType(DataGridViewRowHeaderCellEx)
    End If
End Sub
End Class

 

Public Class DataGridViewRowHeaderCellEx
Inherits DataGridViewRowHeaderCell

Protected Overrides Sub Paint(graphics As System.Drawing.Graphics, clipBounds As System.Drawing.Rectangle, cellBounds As System.Drawing.Rectangle, rowIndex As Integer, dataGridViewElementState As System.Windows.Forms.DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As System.Windows.Forms.DataGridViewCellStyle, advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, paintParts As System.Windows.Forms.DataGridViewPaintParts)
    If Not Me.OwningRow.DataBoundItem Is Nothing Then
        If TypeOf Me.OwningRow.DataBoundItem Is DataRowView Then

        End If
    End If
'HERE YOU CAN USE DATAGRIDROW TAG TO PAINT STRING

    formattedValue = CStr(Me.DataGridView.Rows(rowIndex).Tag)
    MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
End Sub
End Class
jonsca
  • 10,218
  • 26
  • 54
  • 62
Marc
  • 1
0

Like the OnCellToolTipTextNeeded(...) and OnRowErrorTextNeeded(...); built-in methods, there should have been an OnRowHeaderCellValueNeeded(...); method but there isn't one.

There are two protected methods OnRowErrorTextNeeded(...) or OnRowPrePaint(...) that look promising, however there are side-effects trying to use them, i.e. "rowIndex out of bounds". Also, if DoubleBuffered is false then the result is the process crashes.

The method that seems to behave without side-effects is the OnCellErrorTextNeeded(...) method. Looking at the stack trace, that method is called inside of a private PaintWork(...) method, whereas the OnRowErrorTextNeeded(...) method is not.

Also, one requirement seems to be that the row header cell value must be a String object, or it is not drawn.

public class MyDGV : DataGridView {

    // only set the HeaderCell.Value if the row is different than before
    private int onCellErrorTextNeededRowIndexPrevious = -1;

    public MyDGV() {
        this.Dock = DockStyle.Fill;
        this.AllowUserToAddRows = false;
        this.AllowUserToResizeRows = false;
        this.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;
        this.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
        this.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
        this.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        this.DoubleBuffered = true;
    
        DataTable dt = new DataTable();
        dt.Columns.Add("A");
        dt.Columns.Add("B", typeof(DateTime));
        dt.Columns.Add("C", typeof(int));
        int x = 1;
        DateTime date = DateTime.Today.AddDays(-52);
        for (char c = 'A'; c <= 'Z'; c++) {
            dt.Rows.Add(c.ToString().ToLower(), date, x++);
            dt.Rows.Add(c.ToString(), date, x++);
            date = date.AddDays(1);
        }
        this.DataSource = dt;
    }

    protected override void OnCellErrorTextNeeded(DataGridViewCellErrorTextNeededEventArgs e) {
        base.OnCellErrorTextNeeded(e);
        e.ErrorText = "Cell(" + e.ColumnIndex + ", " + e.RowIndex + ")";

        if (e.RowIndex != onCellErrorTextNeededRowIndexPrevious) {
            onCellErrorTextNeededRowIndexPrevious = e.RowIndex;
            DataGridViewRow rs = this.Rows[e.RowIndex]; // HeaderCell requires unshared row
            rs.HeaderCell.Value = (e.RowIndex + 1).ToString();
            //Debug.WriteLine("getting: " + e.ErrorText); // testing only
        }
        else {
            //Debug.WriteLine("skipping"); // testing only
        }
    }

    protected override void OnRowErrorTextNeeded(DataGridViewRowErrorTextNeededEventArgs e) {
        base.OnRowErrorTextNeeded(e);
        e.ErrorText = "Cell(-1, " + e.RowIndex + ")";
    }
}
Loathing
  • 5,109
  • 3
  • 24
  • 35
-2

make sure the Enable Column Recording is checked.

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
Silver
  • 1
-2

Yes. First, hook into the column added event:

this.dataGridView1.ColumnAdded += new DataGridViewColumnEventHandler(dataGridView1_ColumnAdded);

Then, in your event handler, just append the text you want to:

private void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
    e.Column.HeaderText += additionalHeaderText;
}
BFree
  • 102,548
  • 21
  • 159
  • 201
  • Ah, this is for `DataGridViewRow.HeaderCell`. For some reason, C# has trouble setting `HeaderCell.Value`. – Fred F. Apr 24 '10 at 01:11
  • If you place this code in the constructor, it will not work. Move the code into the form's Load event and it should work fine. – AMissico Apr 24 '10 at 21:31
  • 1
    -1: The question was about setting the row header, but the answer shows how to set the column header (which is trivial). – Oliver May 17 '13 at 13:19