The topic you requested is included in another documentation set. For convenience, it's displayed below. Choose Switch to see the topic in its original location.

DataGridView.VirtualMode Property

Gets or sets a value indicating whether you have provided your own data-management operations for the DataGridView control.

Namespace: System.Windows.Forms
Assembly: System.Windows.Forms (in

Public Property VirtualMode As Boolean
Dim instance As DataGridView
Dim value As Boolean

value = instance.VirtualMode

instance.VirtualMode = value
/** @property */
public boolean get_VirtualMode ()

/** @property */
public void set_VirtualMode (boolean value)

public function get VirtualMode () : boolean

public function set VirtualMode (value : boolean)

Not applicable.

Property Value

true if the DataGridView uses data-management operations that you provide; otherwise, false. The default is false.

Virtual mode is designed for use with very large stores of data. When the VirtualMode property is true, you create a DataGridView with a set number of rows and columns and then handle the CellValueNeeded event to populate the cells. Virtual mode requires implementation of an underlying data cache to handle the population, editing, and deletion of DataGridView cells based on actions of the user. For more information about implementing virtual mode, see How to: Implement Virtual Mode in the Windows Forms DataGridView Control.

You must use virtual mode to maintain the values of unbound columns when the DataGridView control is in bound mode. Sorting by unbound columns in bound mode is not supported.

The following code example code uses virtual mode to create a table of positive integers.

Imports System.IO
Imports System.Collections.Generic
Imports System.Windows.Forms

Public Class VirtualModeDemo
    Inherits System.Windows.Forms.Form

    Dim WithEvents dataGridView1 As New DataGridView

    Public Sub New()


        Text = "DataGridView virtual-mode demo (cell-level commit scope)"

        dataGridView1.VirtualMode = True
        dataGridView1.AllowUserToDeleteRows = False
        dataGridView1.Columns.Add("Numbers", "Positive Numbers")
        dataGridView1.Rows.AddCopies(0, initialSize)

    End Sub

    Dim newRowNeeded As Boolean

    Private Sub dataGridView1_NewRowNeeded(ByVal sender As Object, _
        ByVal e As DataGridViewRowEventArgs) _
        Handles dataGridView1.NewRowNeeded

        newRowNeeded = True
    End Sub

    Const initialSize As Integer = 5000000
    Dim numberOfRows As Integer = initialSize

    Private Sub dataGridView1_RowsAdded(ByVal sender As Object, _
        ByVal e As DataGridViewRowsAddedEventArgs) _
        Handles dataGridView1.RowsAdded

        If newRowNeeded Then
            newRowNeeded = False
            numberOfRows = numberOfRows + 1
        End If
    End Sub

#Region "data store maintance"
    Const initialValue As Integer = -1

    Private Sub dataGridView1_CellValueNeeded(ByVal sender As Object, _
        ByVal e As DataGridViewCellValueEventArgs) _
        Handles dataGridView1.CellValueNeeded

        If store.ContainsKey(e.RowIndex) Then
            ' Use the store if the e value has been modified 
            ' and stored.
            e.Value = store(e.RowIndex)
        ElseIf newRowNeeded AndAlso e.RowIndex = numberOfRows Then
            If dataGridView1.IsCurrentCellInEditMode Then
                e.Value = initialValue
                ' Show a blank value if the cursor is just resting
                ' on the last row.
                e.Value = String.Empty
            End If
            e.Value = e.RowIndex
        End If
    End Sub

    Private Sub dataGridView1_CellValuePushed(ByVal sender As Object, _
        ByVal e As DataGridViewCellValueEventArgs) _
        Handles dataGridView1.CellValuePushed

        store.Add(e.RowIndex, CInt(e.Value))

    End Sub
#End Region

    Dim store As System.Collections.Generic.Dictionary(Of Integer, Integer) = _
        New Dictionary(Of Integer, Integer)

    Private Sub dataGridView1_CellValidating(ByVal sender As Object, _
        ByVal e _
        As DataGridViewCellValidatingEventArgs) _
        Handles dataGridView1.CellValidating

        Me.dataGridView1.Rows(e.RowIndex).ErrorText = ""
        Dim newInteger As Integer

        ' Don't try to validate the 'new row' until finished 
        ' editing since there
        ' is not any point in validating its initial value.
        If dataGridView1.Rows(e.RowIndex).IsNewRow Then Return
        If Not Integer.TryParse(e.FormattedValue.ToString(), newInteger) _
            OrElse newInteger < 0 Then

            e.Cancel = True
            Me.dataGridView1.Rows(e.RowIndex).ErrorText = "the value must be a non-negative integer"

        End If
    End Sub

    <STAThreadAttribute()> _
    Public Shared Sub Main()
        Application.Run(New VirtualModeDemo())
    End Sub
End Class

import System.IO.*;
import System.Collections.Generic.*;
import System.Windows.Forms.*;
import System.Drawing.*;
import System.*;

public class Virtual extends Form
    private DataGridView dataGridView1 = new DataGridView();

    public Virtual()
        dataGridView1.add_NewRowNeeded(new DataGridViewRowEventHandler(
        dataGridView1.add_RowsAdded(new DataGridViewRowsAddedEventHandler(
            new DataGridViewCellValidatingEventHandler(
            new DataGridViewCellValueEventHandler(
            new DataGridViewCellValueEventHandler(

        try {
            dataGridView1.get_Columns().Add("Numbers", "Positive Numbers");
            dataGridView1.get_Rows().AddCopies(0, INITIALSIZE);
        catch (System.Exception ex) {
            MessageBox.Show("Exception occured: " + ex.ToString());
    } //Virtual

    private boolean newRowNeeded;

    private void dataGridView1_NewRowNeeded(Object sender,
        DataGridViewRowEventArgs e)
        newRowNeeded = true;
    } //dataGridView1_NewRowNeeded

    private final int INITIALSIZE = 5000000;
    private int numberOfRows = INITIALSIZE;

    private void dataGridView1_RowsAdded(Object sender,
        DataGridViewRowsAddedEventArgs e)
        if (newRowNeeded) {
            newRowNeeded = false;
            numberOfRows = numberOfRows + 1;
    } //dataGridView1_RowsAdded

    #region "data store maintance"
    private final int INITIALVALUE = -1;

    private void dataGridView1_CellValueNeeded(Object sender,
        DataGridViewCellValueEventArgs e)
        if (store.ContainsKey(e.get_RowIndex())) {
            // Use the store if the e value has been modified 
            // and stored.            
        else {
            if (newRowNeeded && e.get_RowIndex() == numberOfRows) {
                if (dataGridView1.get_IsCurrentCellInEditMode()) {
                else {
                    // Show a blank e if the cursor is just loitering
                    // over(the)
                    // last row.
            else {
    } //dataGridView1_CellValueNeeded

    private void dataGridView1_CellValuePushed(Object sender,
        DataGridViewCellValueEventArgs e)
        store.Add(e.get_RowIndex(), Int32.Parse(e.get_Value().ToString()));
    } //dataGridView1_CellValuePushed

    private Dictionary<int, int> store = new Dictionary<int, int>();

    private void dataGridView1_CellValidating(Object sender,
        DataGridViewCellValidatingEventArgs e)
        int newInteger = 0;
        // Don't try to validate the 'new row' until finished 
        // editing since there
        // is not any point in validating its initial value.
        if (dataGridView1.get_Rows().get_Item(
            e.get_RowIndex()).get_IsNewRow()) {
        if (!(Int32.TryParse(e.get_FormattedValue().ToString(), newInteger)) 
            || newInteger < 0) {
    } //dataGridView1_CellValidating

    public static void main(String[] args)
        Application.Run(new Virtual());
    } //main
} //Virtual

Windows 98, Windows Server 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

The Microsoft .NET Framework 3.0 is supported on Windows Vista, Microsoft Windows XP SP2, and Windows Server 2003 SP1.

.NET Framework

Supported in: 3.0, 2.0

Community Additions