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.

To use an unbound DataGridView control

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

    Imports System
    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
        <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 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 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 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.

    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

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.

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:

Community Additions