How to: Implement Virtual Mode in the Windows Forms DataGridView Control
The following code example demonstrates how to manage large sets of data using a DataGridView control with its VirtualMode property set to true.
For a complete explanation of this code example, see Walkthrough: Implementing Virtual Mode in the Windows Forms DataGridView Control.
Example
Imports System
Imports System.Windows.Forms
Public Class Form1
Inherits Form
Private WithEvents dataGridView1 As New DataGridView()
' Declare an ArrayList to serve as the data store.
Private customers As New System.Collections.ArrayList()
' Declare a Customer object to store data for a row being edited.
Private customerInEdit As Customer
' Declare a variable to store the index of a row being edited.
' A value of -1 indicates that there is no row currently in edit.
Private rowInEdit As Integer = -1
' Declare a variable to indicate the commit scope.
' Set this value to false to use cell-level commit scope.
Private rowScopeCommit As Boolean = True
<STAThreadAttribute()> _
Public Shared Sub Main()
Application.Run(New Form1())
End Sub
Public Sub New()
' Initialize the form.
Me.dataGridView1.Dock = DockStyle.Fill
Me.Controls.Add(Me.dataGridView1)
Me.Text = "DataGridView virtual-mode demo (row-level commit scope)"
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles Me.Load
' Enable virtual mode.
Me.dataGridView1.VirtualMode = True
' Add columns to the DataGridView.
Dim companyNameColumn As New DataGridViewTextBoxColumn()
With companyNameColumn
.HeaderText = "Company Name"
.Name = "Company Name"
End With
Dim contactNameColumn As New DataGridViewTextBoxColumn()
With contactNameColumn
.HeaderText = "Contact Name"
.Name = "Contact Name"
End With
Me.dataGridView1.Columns.Add(companyNameColumn)
Me.dataGridView1.Columns.Add(contactNameColumn)
Me.dataGridView1.AutoSizeColumnsMode = _
DataGridViewAutoSizeColumnsMode.AllCells
' Add some sample entries to the data store.
Me.customers.Add(New Customer("Bon app'", "Laurence Lebihan"))
Me.customers.Add(New Customer("Bottom-Dollar Markets", _
"Elizabeth Lincoln"))
Me.customers.Add(New Customer("B's Beverages", "Victoria Ashworth"))
' Set the row count, including the row for new records.
Me.dataGridView1.RowCount = 4
End Sub
Private Sub dataGridView1_CellValueNeeded(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) _
Handles dataGridView1.CellValueNeeded
' If this is the row for new records, no values are needed.
If e.RowIndex = Me.dataGridView1.RowCount - 1 Then
Return
End If
Dim customerTmp As Customer = Nothing
' Store a reference to the Customer object for the row being painted.
If e.RowIndex = rowInEdit Then
customerTmp = Me.customerInEdit
Else
customerTmp = CType(Me.customers(e.RowIndex), Customer)
End If
' Set the cell value to paint using the Customer object retrieved.
Select Case Me.dataGridView1.Columns(e.ColumnIndex).Name
Case "Company Name"
e.Value = customerTmp.CompanyName
Case "Contact Name"
e.Value = customerTmp.ContactName
End Select
End Sub
Private Sub dataGridView1_CellValuePushed(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellValueEventArgs) _
Handles dataGridView1.CellValuePushed
Dim customerTmp As Customer = Nothing
' Store a reference to the Customer object for the row being edited.
If e.RowIndex < Me.customers.Count Then
' If the user is editing a new row, create a new Customer object.
If Me.customerInEdit Is Nothing Then
Me.customerInEdit = New Customer( _
CType(Me.customers(e.RowIndex), Customer).CompanyName, _
CType(Me.customers(e.RowIndex), Customer).ContactName)
End If
customerTmp = Me.customerInEdit
Me.rowInEdit = e.RowIndex
Else
customerTmp = Me.customerInEdit
End If
' Set the appropriate Customer property to the cell value entered.
Dim newValue As String = TryCast(e.Value, String)
Select Case Me.dataGridView1.Columns(e.ColumnIndex).Name
Case "Company Name"
customerTmp.CompanyName = newValue
Case "Contact Name"
customerTmp.ContactName = newValue
End Select
End Sub
Private Sub dataGridView1_NewRowNeeded(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewRowEventArgs) _
Handles dataGridView1.NewRowNeeded
' Create a new Customer object when the user edits
' the row for new records.
Me.customerInEdit = New Customer()
Me.rowInEdit = Me.dataGridView1.Rows.Count - 1
End Sub
Private Sub dataGridView1_RowValidated(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
Handles dataGridView1.RowValidated
' Save row changes if any were made and release the edited
' Customer object if there is one.
If e.RowIndex >= Me.customers.Count AndAlso _
e.RowIndex <> Me.dataGridView1.Rows.Count - 1 Then
' Add the new Customer object to the data store.
Me.customers.Add(Me.customerInEdit)
Me.customerInEdit = Nothing
Me.rowInEdit = -1
ElseIf (Me.customerInEdit IsNot Nothing) AndAlso _
e.RowIndex < Me.customers.Count Then
' Save the modified Customer object in the data store.
Me.customers(e.RowIndex) = Me.customerInEdit
Me.customerInEdit = Nothing
Me.rowInEdit = -1
ElseIf Me.dataGridView1.ContainsFocus Then
Me.customerInEdit = Nothing
Me.rowInEdit = -1
End If
End Sub
Private Sub dataGridView1_RowDirtyStateNeeded(ByVal sender As Object, _
ByVal e As System.Windows.Forms.QuestionEventArgs) _
Handles dataGridView1.RowDirtyStateNeeded
If Not rowScopeCommit Then
' In cell-level commit scope, indicate whether the value
' of the current cell has been modified.
e.Response = Me.dataGridView1.IsCurrentCellDirty
End If
End Sub
Private Sub dataGridView1_CancelRowEdit(ByVal sender As Object, _
ByVal e As System.Windows.Forms.QuestionEventArgs) _
Handles dataGridView1.CancelRowEdit
If Me.rowInEdit = Me.dataGridView1.Rows.Count - 2 AndAlso _
Me.rowInEdit = Me.customers.Count Then
' If the user has canceled the edit of a newly created row,
' replace the corresponding Customer object with a new, empty one.
Me.customerInEdit = New Customer()
Else
' If the user has canceled the edit of an existing row,
' release the corresponding Customer object.
Me.customerInEdit = Nothing
Me.rowInEdit = -1
End If
End Sub
Private Sub dataGridView1_UserDeletingRow(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewRowCancelEventArgs) _
Handles dataGridView1.UserDeletingRow
If e.Row.Index < Me.customers.Count Then
' If the user has deleted an existing row, remove the
' corresponding Customer object from the data store.
Me.customers.RemoveAt(e.Row.Index)
End If
If e.Row.Index = Me.rowInEdit Then
' If the user has deleted a newly created row, release
' the corresponding Customer object.
Me.rowInEdit = -1
Me.customerInEdit = Nothing
End If
End Sub
End Class
Public Class Customer
Private companyNameValue As String
Private contactNameValue As String
Public Sub New()
' Leave fields empty.
End Sub
Public Sub New(ByVal companyName As String, ByVal contactName As String)
companyNameValue = companyName
contactNameValue = contactName
End Sub
Public Property CompanyName() As String
Get
Return companyNameValue
End Get
Set(ByVal value As String)
companyNameValue = value
End Set
End Property
Public Property ContactName() As String
Get
Return contactNameValue
End Get
Set(ByVal value As String)
contactNameValue = value
End Set
End Property
End Class
using System;
using System.Windows.Forms;
public class Form1 : Form
{
private DataGridView dataGridView1 = new DataGridView();
// Declare an ArrayList to serve as the data store.
private System.Collections.ArrayList customers =
new System.Collections.ArrayList();
// Declare a Customer object to store data for a row being edited.
private Customer customerInEdit;
// Declare a variable to store the index of a row being edited.
// A value of -1 indicates that there is no row currently in edit.
private int rowInEdit = -1;
// Declare a variable to indicate the commit scope.
// Set this value to false to use cell-level commit scope.
private bool rowScopeCommit = true;
[STAThreadAttribute()]
public static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
// Initialize the form.
this.dataGridView1.Dock = DockStyle.Fill;
this.Controls.Add(this.dataGridView1);
this.Load += new EventHandler(Form1_Load);
this.Text = "DataGridView virtual-mode demo (row-level commit scope)";
}
private void Form1_Load(object sender, EventArgs e)
{
// Enable virtual mode.
this.dataGridView1.VirtualMode = true;
// Connect the virtual-mode events to event handlers.
this.dataGridView1.CellValueNeeded += new
DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
this.dataGridView1.CellValuePushed += new
DataGridViewCellValueEventHandler(dataGridView1_CellValuePushed);
this.dataGridView1.NewRowNeeded += new
DataGridViewRowEventHandler(dataGridView1_NewRowNeeded);
this.dataGridView1.RowValidated += new
DataGridViewCellEventHandler(dataGridView1_RowValidated);
this.dataGridView1.RowDirtyStateNeeded += new
QuestionEventHandler(dataGridView1_RowDirtyStateNeeded);
this.dataGridView1.CancelRowEdit += new
QuestionEventHandler(dataGridView1_CancelRowEdit);
this.dataGridView1.UserDeletingRow += new
DataGridViewRowCancelEventHandler(dataGridView1_UserDeletingRow);
// Add columns to the DataGridView.
DataGridViewTextBoxColumn companyNameColumn = new
DataGridViewTextBoxColumn();
companyNameColumn.HeaderText = "Company Name";
companyNameColumn.Name = "Company Name";
DataGridViewTextBoxColumn contactNameColumn = new
DataGridViewTextBoxColumn();
contactNameColumn.HeaderText = "Contact Name";
contactNameColumn.Name = "Contact Name";
this.dataGridView1.Columns.Add(companyNameColumn);
this.dataGridView1.Columns.Add(contactNameColumn);
this.dataGridView1.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
// Add some sample entries to the data store.
this.customers.Add(new Customer(
"Bon app'", "Laurence Lebihan"));
this.customers.Add(new Customer(
"Bottom-Dollar Markets", "Elizabeth Lincoln"));
this.customers.Add(new Customer(
"B's Beverages", "Victoria Ashworth"));
// Set the row count, including the row for new records.
this.dataGridView1.RowCount = 4;
}
private void dataGridView1_CellValueNeeded(object sender,
System.Windows.Forms.DataGridViewCellValueEventArgs e)
{
// If this is the row for new records, no values are needed.
if (e.RowIndex == this.dataGridView1.RowCount - 1) return;
Customer customerTmp = null;
// Store a reference to the Customer object for the row being painted.
if (e.RowIndex == rowInEdit)
{
customerTmp = this.customerInEdit;
}
else
{
customerTmp = (Customer)this.customers[e.RowIndex];
}
// Set the cell value to paint using the Customer object retrieved.
switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
{
case "Company Name":
e.Value = customerTmp.CompanyName;
break;
case "Contact Name":
e.Value = customerTmp.ContactName;
break;
}
}
private void dataGridView1_CellValuePushed(object sender,
System.Windows.Forms.DataGridViewCellValueEventArgs e)
{
Customer customerTmp = null;
// Store a reference to the Customer object for the row being edited.
if (e.RowIndex < this.customers.Count)
{
// If the user is editing a new row, create a new Customer object.
if (this.customerInEdit == null)
{
this.customerInEdit = new Customer(
((Customer)this.customers[e.RowIndex]).CompanyName,
((Customer)this.customers[e.RowIndex]).ContactName);
}
customerTmp = this.customerInEdit;
this.rowInEdit = e.RowIndex;
}
else
{
customerTmp = this.customerInEdit;
}
// Set the appropriate Customer property to the cell value entered.
String newValue = e.Value as String;
switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
{
case "Company Name":
customerTmp.CompanyName = newValue;
break;
case "Contact Name":
customerTmp.ContactName = newValue;
break;
}
}
private void dataGridView1_NewRowNeeded(object sender,
System.Windows.Forms.DataGridViewRowEventArgs e)
{
// Create a new Customer object when the user edits
// the row for new records.
this.customerInEdit = new Customer();
this.rowInEdit = this.dataGridView1.Rows.Count - 1;
}
private void dataGridView1_RowValidated(object sender,
System.Windows.Forms.DataGridViewCellEventArgs e)
{
// Save row changes if any were made and release the edited
// Customer object if there is one.
if (e.RowIndex >= this.customers.Count &&
e.RowIndex != this.dataGridView1.Rows.Count - 1)
{
// Add the new Customer object to the data store.
this.customers.Add(this.customerInEdit);
this.customerInEdit = null;
this.rowInEdit = -1;
}
else if (this.customerInEdit != null &&
e.RowIndex < this.customers.Count)
{
// Save the modified Customer object in the data store.
this.customers[e.RowIndex] = this.customerInEdit;
this.customerInEdit = null;
this.rowInEdit = -1;
}
else if (this.dataGridView1.ContainsFocus)
{
this.customerInEdit = null;
this.rowInEdit = -1;
}
}
private void dataGridView1_RowDirtyStateNeeded(object sender,
System.Windows.Forms.QuestionEventArgs e)
{
if (!rowScopeCommit)
{
// In cell-level commit scope, indicate whether the value
// of the current cell has been modified.
e.Response = this.dataGridView1.IsCurrentCellDirty;
}
}
private void dataGridView1_CancelRowEdit(object sender,
System.Windows.Forms.QuestionEventArgs e)
{
if (this.rowInEdit == this.dataGridView1.Rows.Count - 2 &&
this.rowInEdit == this.customers.Count)
{
// If the user has canceled the edit of a newly created row,
// replace the corresponding Customer object with a new, empty one.
this.customerInEdit = new Customer();
}
else
{
// If the user has canceled the edit of an existing row,
// release the corresponding Customer object.
this.customerInEdit = null;
this.rowInEdit = -1;
}
}
private void dataGridView1_UserDeletingRow(object sender,
System.Windows.Forms.DataGridViewRowCancelEventArgs e)
{
if (e.Row.Index < this.customers.Count)
{
// If the user has deleted an existing row, remove the
// corresponding Customer object from the data store.
this.customers.RemoveAt(e.Row.Index);
}
if (e.Row.Index == this.rowInEdit)
{
// If the user has deleted a newly created row, release
// the corresponding Customer object.
this.rowInEdit = -1;
this.customerInEdit = null;
}
}
}
public class Customer
{
private String companyNameValue;
private String contactNameValue;
public Customer()
{
// Leave fields empty.
}
public Customer(String companyName, String contactName)
{
companyNameValue = companyName;
contactNameValue = contactName;
}
public String CompanyName
{
get
{
return companyNameValue;
}
set
{
companyNameValue = value;
}
}
public String ContactName
{
get
{
return contactNameValue;
}
set
{
contactNameValue = value;
}
}
}
#using <System.Drawing.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
public ref class Customer
{
private:
String^ companyNameValue;
String^ contactNameValue;
public:
Customer()
{
// Leave fields empty.
}
Customer( String^ companyName, String^ contactName )
{
companyNameValue = companyName;
contactNameValue = contactName;
}
property String^ CompanyName
{
String^ get()
{
return companyNameValue;
}
void set( String^ value )
{
companyNameValue = value;
}
}
property String^ ContactName
{
String^ get()
{
return contactNameValue;
}
void set( String^ value )
{
contactNameValue = value;
}
}
};
public ref class Form1: public Form
{
private:
DataGridView^ dataGridView1;
// Declare an ArrayList to serve as the data store.
System::Collections::ArrayList^ customers;
// Declare a Customer object to store data for a row being edited.
Customer^ customerInEdit;
// Declare a variable to store the index of a row being edited.
// A value of -1 indicates that there is no row currently in edit.
int rowInEdit;
// Declare a variable to indicate the commit scope.
// Set this value to false to use cell-level commit scope.
bool rowScopeCommit;
public:
static void Main()
{
Application::Run( gcnew Form1 );
}
Form1()
{
dataGridView1 = gcnew DataGridView;
customers = gcnew System::Collections::ArrayList;
rowInEdit = -1;
rowScopeCommit = true;
// Initialize the form.
this->dataGridView1->Dock = DockStyle::Fill;
this->Controls->Add( this->dataGridView1 );
this->Load += gcnew EventHandler( this, &Form1::Form1_Load );
}
private:
void Form1_Load( Object^ /*sender*/, EventArgs^ /*e*/ )
{
// Enable virtual mode.
this->dataGridView1->VirtualMode = true;
// Connect the virtual-mode events to event handlers.
this->dataGridView1->CellValueNeeded += gcnew
DataGridViewCellValueEventHandler( this, &Form1::dataGridView1_CellValueNeeded );
this->dataGridView1->CellValuePushed += gcnew
DataGridViewCellValueEventHandler( this, &Form1::dataGridView1_CellValuePushed );
this->dataGridView1->NewRowNeeded += gcnew
DataGridViewRowEventHandler( this, &Form1::dataGridView1_NewRowNeeded );
this->dataGridView1->RowValidated += gcnew
DataGridViewCellEventHandler( this, &Form1::dataGridView1_RowValidated );
this->dataGridView1->RowDirtyStateNeeded += gcnew
QuestionEventHandler( this, &Form1::dataGridView1_RowDirtyStateNeeded );
this->dataGridView1->CancelRowEdit += gcnew
QuestionEventHandler( this, &Form1::dataGridView1_CancelRowEdit );
this->dataGridView1->UserDeletingRow += gcnew
DataGridViewRowCancelEventHandler( this, &Form1::dataGridView1_UserDeletingRow );
// Add columns to the DataGridView.
DataGridViewTextBoxColumn^ companyNameColumn = gcnew DataGridViewTextBoxColumn;
companyNameColumn->HeaderText = L"Company Name";
companyNameColumn->Name = L"Company Name";
DataGridViewTextBoxColumn^ contactNameColumn = gcnew DataGridViewTextBoxColumn;
contactNameColumn->HeaderText = L"Contact Name";
contactNameColumn->Name = L"Contact Name";
this->dataGridView1->Columns->Add( companyNameColumn );
this->dataGridView1->Columns->Add( contactNameColumn );
this->dataGridView1->AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode::AllCells;
// Add some sample entries to the data store.
this->customers->Add( gcnew Customer( L"Bon app'",L"Laurence Lebihan" ) );
this->customers->Add( gcnew Customer( L"Bottom-Dollar Markets",L"Elizabeth Lincoln" ) );
this->customers->Add( gcnew Customer( L"B's Beverages",L"Victoria Ashworth" ) );
// Set the row count, including the row for new records.
this->dataGridView1->RowCount = 4;
}
void dataGridView1_CellValueNeeded( Object^ /*sender*/,
System::Windows::Forms::DataGridViewCellValueEventArgs^ e )
{
Customer^ customerTmp = nullptr;
// Store a reference to the Customer object for the row being painted.
if ( e->RowIndex == rowInEdit )
{
customerTmp = this->customerInEdit;
}
else
{
customerTmp = dynamic_cast<Customer^>(this->customers[ e->RowIndex ]);
}
// Set the cell value to paint using the Customer object retrieved.
int switchcase = 0;
if ( (this->dataGridView1->Columns[ e->ColumnIndex ]->Name)->Equals( L"Company Name" ) )
switchcase = 1;
else
if ( (this->dataGridView1->Columns[ e->ColumnIndex ]->Name)->Equals( L"Contact Name" ) )
switchcase = 2;
switch ( switchcase )
{
case 1:
e->Value = customerTmp->CompanyName;
break;
case 2:
e->Value = customerTmp->ContactName;
break;
}
}
void dataGridView1_CellValuePushed( Object^ /*sender*/,
System::Windows::Forms::DataGridViewCellValueEventArgs^ e )
{
Customer^ customerTmp = nullptr;
// Store a reference to the Customer object for the row being edited.
if ( e->RowIndex < this->customers->Count )
{
// If the user is editing a new row, create a new Customer object.
if ( this->customerInEdit == nullptr )
{
this->customerInEdit = gcnew Customer(
(dynamic_cast<Customer^>(this->customers[ e->RowIndex ]))->CompanyName,
(dynamic_cast<Customer^>(this->customers[ e->RowIndex ])->ContactName) );
}
customerTmp = this->customerInEdit;
this->rowInEdit = e->RowIndex;
}
else
{
customerTmp = this->customerInEdit;
}
// Set the appropriate Customer property to the cell value entered.
int switchcase = 0;
if ( (this->dataGridView1->Columns[ e->ColumnIndex ]->Name)->Equals( L"Company Name" ) )
switchcase = 1;
else
if ( (this->dataGridView1->Columns[ e->ColumnIndex ]->Name)->Equals( L"Contact Name" ) )
switchcase = 2;
switch ( switchcase )
{
case 1:
customerTmp->CompanyName = dynamic_cast<String^>(e->Value);
break;
case 2:
customerTmp->ContactName = dynamic_cast<String^>(e->Value);
break;
}
}
void dataGridView1_NewRowNeeded( Object^ /*sender*/,
System::Windows::Forms::DataGridViewRowEventArgs^ /*e*/ )
{
// Create a new Customer object when the user edits
// the row for new records.
this->customerInEdit = gcnew Customer;
this->rowInEdit = this->dataGridView1->Rows->Count - 1;
}
void dataGridView1_RowValidated( Object^ /*sender*/,
System::Windows::Forms::DataGridViewCellEventArgs^ e )
{
// Save row changes if any were made and release the edited
// Customer object if there is one.
if ( e->RowIndex >= this->customers->Count && e->RowIndex != this->dataGridView1->Rows->Count - 1 )
{
// Add the new Customer object to the data store.
this->customers->Add( this->customerInEdit );
this->customerInEdit = nullptr;
this->rowInEdit = -1;
}
else
if ( this->customerInEdit != nullptr && e->RowIndex < this->customers->Count )
{
// Save the modified Customer object in the data store.
this->customers[ e->RowIndex ] = this->customerInEdit;
this->customerInEdit = nullptr;
this->rowInEdit = -1;
}
else
if ( this->dataGridView1->ContainsFocus )
{
this->customerInEdit = nullptr;
this->rowInEdit = -1;
}
}
void dataGridView1_RowDirtyStateNeeded( Object^ /*sender*/,
System::Windows::Forms::QuestionEventArgs^ e )
{
if ( !rowScopeCommit )
{
// In cell-level commit scope, indicate whether the value
// of the current cell has been modified.
e->Response = this->dataGridView1->IsCurrentCellDirty;
}
}
void dataGridView1_CancelRowEdit( Object^ /*sender*/,
System::Windows::Forms::QuestionEventArgs^ /*e*/ )
{
if ( this->rowInEdit == this->dataGridView1->Rows->Count - 2 &&
this->rowInEdit == this->customers->Count )
{
// If the user has canceled the edit of a newly created row,
// replace the corresponding Customer object with a new, empty one.
this->customerInEdit = gcnew Customer;
}
else
{
// If the user has canceled the edit of an existing row,
// release the corresponding Customer object.
this->customerInEdit = nullptr;
this->rowInEdit = -1;
}
}
void dataGridView1_UserDeletingRow( Object^ /*sender*/,
System::Windows::Forms::DataGridViewRowCancelEventArgs^ e )
{
if ( e->Row->Index < this->customers->Count )
{
// If the user has deleted an existing row, remove the
// corresponding Customer object from the data store.
this->customers->RemoveAt( e->Row->Index );
}
if ( e->Row->Index == this->rowInEdit )
{
// If the user has deleted a newly created row, release
// the corresponding Customer object.
this->rowInEdit = -1;
this->customerInEdit = nullptr;
}
}
};
int main()
{
Form1::Main();
}
Compiling the Code
This example requires:
- References to the System and System.Windows.Forms assemblies.
For information about building this example from the command line for Visual Basic or Visual C#, see Building from the Command Line (Visual Basic) or Command-line Building With csc.exe. You can also build this example in Visual Studio by pasting the code into a new project. For more information, see How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio.
See Also
Tasks
Walkthrough: Implementing Virtual Mode in the Windows Forms DataGridView Control
Reference
Concepts
Virtual Mode in the Windows Forms DataGridView Control
Other Resources
Performance Tuning in the Windows Forms DataGridView Control