Walkthrough: Creating an Unbound Windows Forms DataGridView Control

You may frequently want to display tabular data that does not originate from a database. For example, you may want to show the contents of a two-dimensional array of strings. The DataGridView class provides an easy and highly customizable way to display data without binding to a data source. This walkthrough shows how to populate a DataGridView control and manage the addition and deletion of rows in "unbound" mode. By default, the user can add new rows. To prevent row addition, set the AllowUserToAddRows property is false.

To copy the code in this topic as a single listing, see How to: Create an Unbound Windows Forms DataGridView Control.

Creating the Form

To use an unbound DataGridView control

  1. Create a class that derives from Form and contains the following variable declarations and Main method.

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    public class Form1 : System.Windows.Forms.Form
        private Panel buttonPanel = new Panel();
        private DataGridView songsDataGridView = new DataGridView();
        private Button addNewRowButton = new Button();
        private Button deleteRowButton = new Button();
    Imports System.Drawing
    Imports System.Windows.Forms
    Public Class Form1
        Inherits System.Windows.Forms.Form
        Private buttonPanel As New Panel
        Private WithEvents songsDataGridView As New DataGridView
        Private WithEvents addNewRowButton As New Button
        Private WithEvents deleteRowButton As New Button
        static void Main()
            Application.Run(new Form1());
        <STAThreadAttribute()> _
        Public Shared Sub Main()
            Application.Run(New Form1())
        End Sub
    End Class
  2. Implement a SetupLayout method in your form's class definition to set up the form's layout.

    private void SetupLayout()
        this.Size = new Size(600, 500);
        addNewRowButton.Text = "Add Row";
        addNewRowButton.Location = new Point(10, 10);
        addNewRowButton.Click += new EventHandler(addNewRowButton_Click);
        deleteRowButton.Text = "Delete Row";
        deleteRowButton.Location = new Point(100, 10);
        deleteRowButton.Click += new EventHandler(deleteRowButton_Click);
        buttonPanel.Height = 50;
        buttonPanel.Dock = DockStyle.Bottom;
    Private Sub SetupLayout()
        Me.Size = New Size(600, 500)
        With addNewRowButton
            .Text = "Add Row"
            .Location = New Point(10, 10)
        End With
        With deleteRowButton
            .Text = "Delete Row"
            .Location = New Point(100, 10)
        End With
        With buttonPanel
            .Height = 50
            .Dock = DockStyle.Bottom
        End With
    End Sub
  3. Create a SetupDataGridView method to set up the DataGridView columns and properties.

    This method first adds the DataGridView control to the form's Controls collection. Next, the number of columns to be displayed is set using the ColumnCount property. The default style for the column headers is set by setting the BackColor, ForeColor, and Font properties of the DataGridViewCellStyle returned by the ColumnHeadersDefaultCellStyle property.

    Layout and appearance properties are set, and then the column names are assigned. When this method exits, the DataGridView control is ready to be populated.

    private void SetupDataGridView()
        songsDataGridView.ColumnCount = 5;
        songsDataGridView.ColumnHeadersDefaultCellStyle.BackColor = Color.Navy;
        songsDataGridView.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
        songsDataGridView.ColumnHeadersDefaultCellStyle.Font =
            new Font(songsDataGridView.Font, FontStyle.Bold);
        songsDataGridView.Name = "songsDataGridView";
        songsDataGridView.Location = new Point(8, 8);
        songsDataGridView.Size = new Size(500, 250);
        songsDataGridView.AutoSizeRowsMode =
        songsDataGridView.ColumnHeadersBorderStyle =
        songsDataGridView.CellBorderStyle = DataGridViewCellBorderStyle.Single;
        songsDataGridView.GridColor = Color.Black;
        songsDataGridView.RowHeadersVisible = false;
        songsDataGridView.Columns[0].Name = "Release Date";
        songsDataGridView.Columns[1].Name = "Track";
        songsDataGridView.Columns[2].Name = "Title";
        songsDataGridView.Columns[3].Name = "Artist";
        songsDataGridView.Columns[4].Name = "Album";
        songsDataGridView.Columns[4].DefaultCellStyle.Font =
            new Font(songsDataGridView.DefaultCellStyle.Font, FontStyle.Italic);
        songsDataGridView.SelectionMode =
        songsDataGridView.MultiSelect = false;
        songsDataGridView.Dock = DockStyle.Fill;
        songsDataGridView.CellFormatting += new
    Private Sub SetupDataGridView()
        songsDataGridView.ColumnCount = 5
        With songsDataGridView.ColumnHeadersDefaultCellStyle
            .BackColor = Color.Navy
            .ForeColor = Color.White
            .Font = New Font(songsDataGridView.Font, FontStyle.Bold)
        End With
        With songsDataGridView
            .Name = "songsDataGridView"
            .Location = New Point(8, 8)
            .Size = New Size(500, 250)
            .AutoSizeRowsMode = _
            .ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single
            .CellBorderStyle = DataGridViewCellBorderStyle.Single
            .GridColor = Color.Black
            .RowHeadersVisible = False
            .Columns(0).Name = "Release Date"
            .Columns(1).Name = "Track"
            .Columns(2).Name = "Title"
            .Columns(3).Name = "Artist"
            .Columns(4).Name = "Album"
            .Columns(4).DefaultCellStyle.Font = _
                New Font(Me.songsDataGridView.DefaultCellStyle.Font, FontStyle.Italic)
            .SelectionMode = DataGridViewSelectionMode.FullRowSelect
            .MultiSelect = False
            .Dock = DockStyle.Fill
        End With
    End Sub
  4. Create a PopulateDataGridView method to add rows to the DataGridView control.

    Each row represents a song and its associated information.

    private void PopulateDataGridView()
        string[] row0 = { "11/22/1968", "29", "Revolution 9",
            "Beatles", "The Beatles [White Album]" };
        string[] row1 = { "1960", "6", "Fools Rush In",
            "Frank Sinatra", "Nice 'N' Easy" };
        string[] row2 = { "11/11/1971", "1", "One of These Days",
            "Pink Floyd", "Meddle" };
        string[] row3 = { "1988", "7", "Where Is My Mind?",
            "Pixies", "Surfer Rosa" };
        string[] row4 = { "5/1981", "9", "Can't Find My Mind",
            "Cramps", "Psychedelic Jungle" };
        string[] row5 = { "6/10/2003", "13",
            "Scatterbrain. (As Dead As Leaves.)",
            "Radiohead", "Hail to the Thief" };
        string[] row6 = { "6/30/1992", "3", "Dress", "P J Harvey", "Dry" };
        songsDataGridView.Columns[0].DisplayIndex = 3;
        songsDataGridView.Columns[1].DisplayIndex = 4;
        songsDataGridView.Columns[2].DisplayIndex = 0;
        songsDataGridView.Columns[3].DisplayIndex = 1;
        songsDataGridView.Columns[4].DisplayIndex = 2;
    Private Sub PopulateDataGridView()
        Dim row0 As String() = {"11/22/1968", "29", "Revolution 9", _
            "Beatles", "The Beatles [White Album]"}
        Dim row1 As String() = {"1960", "6", "Fools Rush In", _
            "Frank Sinatra", "Nice 'N' Easy"}
        Dim row2 As String() = {"11/11/1971", "1", "One of These Days", _
            "Pink Floyd", "Meddle"}
        Dim row3 As String() = {"1988", "7", "Where Is My Mind?", _
            "Pixies", "Surfer Rosa"}
        Dim row4 As String() = {"5/1981", "9", "Can't Find My Mind", _
            "Cramps", "Psychedelic Jungle"}
        Dim row5 As String() = {"6/10/2003", "13", _
            "Scatterbrain. (As Dead As Leaves.)", _
            "Radiohead", "Hail to the Thief"}
        Dim row6 As String() = {"6/30/1992", "3", "Dress", "P J Harvey", "Dry"}
        With Me.songsDataGridView.Rows
        End With
        With Me.songsDataGridView
            .Columns(0).DisplayIndex = 3
            .Columns(1).DisplayIndex = 4
            .Columns(2).DisplayIndex = 0
            .Columns(3).DisplayIndex = 1
            .Columns(4).DisplayIndex = 2
        End With
    End Sub
  5. With the utility methods in place, you can attach event handlers.

    You will handle the Add and Delete buttons' Click events, the form's Load event, and the DataGridView control's CellFormatting event.

    When the Add button's Click event is raised, a new, empty row is added to the DataGridView.

    When the Delete button's Click event is raised, the selected row is deleted, unless it is the row for new records, which enables the user add new rows. This row is always the last row in the DataGridView control.

    When the form's Load event is raised, the SetupLayout, SetupDataGridView, and PopulateDataGridView utility methods are called.

    When the CellFormatting event is raised, each cell in the Date column is formatted as a long date, unless the cell's value cannot be parsed.

    public Form1()
        this.Load += new EventHandler(Form1_Load);
    private void Form1_Load(System.Object sender, System.EventArgs e)
    private void songsDataGridView_CellFormatting(object sender,
        System.Windows.Forms.DataGridViewCellFormattingEventArgs e)
        if (e != null)
            if (this.songsDataGridView.Columns[e.ColumnIndex].Name == "Release Date")
                if (e.Value != null)
                        e.Value = DateTime.Parse(e.Value.ToString())
                        e.FormattingApplied = true;
                    catch (FormatException)
                        Console.WriteLine("{0} is not a valid date.", e.Value.ToString());
    private void addNewRowButton_Click(object sender, EventArgs e)
    private void deleteRowButton_Click(object sender, EventArgs e)
        if (this.songsDataGridView.SelectedRows.Count > 0 &&
            this.songsDataGridView.SelectedRows[0].Index !=
            this.songsDataGridView.Rows.Count - 1)
    Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    End Sub
    Private Sub songsDataGridView_CellFormatting(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) _
        Handles songsDataGridView.CellFormatting
        If e IsNot Nothing Then
            If Me.songsDataGridView.Columns(e.ColumnIndex).Name = _
            "Release Date" Then
                If e.Value IsNot Nothing Then
                        e.Value = DateTime.Parse(e.Value.ToString()) _
                        e.FormattingApplied = True
                    Catch ex As FormatException
                        Console.WriteLine("{0} is not a valid date.", e.Value.ToString())
                    End Try
                End If
            End If
        End If
    End Sub
    Private Sub addNewRowButton_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles addNewRowButton.Click
    End Sub
    Private Sub deleteRowButton_Click(ByVal sender As Object, _
        ByVal e As EventArgs) Handles deleteRowButton.Click
        If Me.songsDataGridView.SelectedRows.Count > 0 AndAlso _
            Not Me.songsDataGridView.SelectedRows(0).Index = _
            Me.songsDataGridView.Rows.Count - 1 Then
            Me.songsDataGridView.Rows.RemoveAt( _
        End If
    End Sub

Testing the Application

You can now test the form to make sure it behaves as expected.

To test the form

  • Press F5 to run the application.

    You will see a DataGridView control that displays the songs listed in PopulateDataGridView. You can add new rows with the Add Row button, and you can delete selected rows with the Delete Row button. The unbound DataGridView control is the data store, and its data is independent of any external source, such as a DataSet or an array.

Next Steps

This application gives you a basic understanding of the DataGridView control's capabilities. You can customize the appearance and behavior of the DataGridView control in several ways:

See also