Share via


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 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";
      companyNameColumn->AutoSizeCriteria = DataGridViewAutoSizeColumnCriteria::HeaderAndRows;
      DataGridViewTextBoxColumn^ contactNameColumn = gcnew DataGridViewTextBoxColumn;
      contactNameColumn->HeaderText = L"Contact Name";
      contactNameColumn->Name = L"Contact Name";
      contactNameColumn->AutoSizeCriteria = DataGridViewAutoSizeColumnCriteria::HeaderAndRows;
      this->dataGridView1->Columns->Add( companyNameColumn );
      this->dataGridView1->Columns->Add( contactNameColumn );

      // 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();
}

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;
      }

   }

};

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. How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio
How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio
How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio
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

Concepts

Virtual Mode in the Windows Forms DataGridView Control

Reference

DataGridView

VirtualMode

CellValueNeeded

CellValuePushed

NewRowNeeded

RowValidated

RowDirtyStateNeeded

CancelRowEdit

UserDeletingRow

Other Resources

Performance Tuning in the Windows Forms DataGridView Control