Procedura dettagliata: implementazione della modalità virtuale nel controllo DataGridView Windows Form

Quando si desidera visualizzare quantità molto elevate di dati tabulari in un DataGridView controllo, è possibile impostare la VirtualMode proprietà su true e gestire in modo esplicito l'interazione del controllo con il relativo archivio dati. In questo modo è possibile ottimizzare le prestazioni del controllo in questa situazione.

Il DataGridView controllo fornisce diversi eventi che è possibile gestire per interagire con un archivio dati personalizzato. Questa procedura dettagliata illustra il processo di implementazione di questi gestori eventi. L'esempio di codice in questo argomento usa un'origine dati molto semplice a scopo illustrativo. In un'impostazione di produzione, in genere si caricheranno solo le righe da visualizzare in una cache e si gestiranno DataGridView gli eventi per interagire e aggiornare la cache. Per altre informazioni, vedere Implementazione della modalità virtuale con caricamento di dati JIT nel controllo DataGridView Windows Form

Per copiare il codice in questo argomento come elenco singolo, vedere Procedura: Implementare la modalità virtuale nel controllo DataGridView Windows Form.

Creazione del form

Per implementare la modalità virtuale

  1. Creare una classe che deriva da Form e contiene un DataGridView controllo .

    Il codice seguente contiene alcune inizializzazione di base. Dichiara alcune variabili che verranno usate nei passaggi successivi, fornisce un Main metodo e fornisce un layout di modulo semplice nel costruttore della classe.

    #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:
    
    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)";
        }
    
    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
    
    };
    
    int main()
    {
       Form1::Main();
    }
    
    }
    
    
    End Class
    
  2. Implementare un gestore per l'evento del Load modulo che inizializza il DataGridView controllo e popola l'archivio dati con valori di esempio.

    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::DisplayedCells;
       
       // 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;
    }
    
    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.DisplayedCells;
    
        // 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 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.DisplayedCells
    
        ' 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
    
  3. Implementare un gestore per l'evento CellValueNeeded che recupera il valore della cella richiesta dall'archivio dati o dall'oggetto Customer attualmente in fase di modifica.

    Questo evento si verifica ogni volta che il DataGridView controllo deve disegnare una cella.

    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;
       }
    }
    
    
    
    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 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
    
  4. Implementare un gestore per l'evento CellValuePushed che archivia un valore di cella modificato nell'oggetto Customer che rappresenta la riga modificata. Questo evento si verifica ogni volta che l'utente esegue il commit di una modifica del valore della cella.

    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;
       }
    }
    
    
    
    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.
            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 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
    
  5. Implementare un gestore per l'evento NewRowNeeded che crea un nuovo Customer oggetto che rappresenta una riga appena creata.

    Questo evento si verifica ogni volta che l'utente immette la riga per i nuovi record.

    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;
    }
    
    
    
    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 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
    
  6. Implementare un gestore per l'evento RowValidated che salva righe nuove o modificate nell'archivio dati.

    Questo evento si verifica ogni volta che l'utente modifica la riga corrente.

    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;
       }
    }
    
    
    
    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 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
    
  7. Implementare un gestore per l'evento RowDirtyStateNeeded che indica se l'evento CancelRowEdit si verificherà quando l'utente segnala la riversione delle righe premendo ESC due volte in modalità di modifica o una volta all'esterno della modalità di modifica.

    Per impostazione predefinita, CancelRowEdit si verifica in caso di riversione delle righe quando sono state modificate celle nella riga corrente, a meno che la QuestionEventArgs.Response proprietà non sia impostata su true nel RowDirtyStateNeeded gestore eventi. Questo evento è utile quando l'ambito di commit viene determinato in fase di esecuzione.

    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_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 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
    
  8. Implementare un gestore per l'evento CancelRowEdit che rimuove i valori dell'oggetto Customer che rappresenta la riga corrente.

    Questo evento si verifica quando l'utente segnala la riversione delle righe premendo ESC due volte in modalità di modifica o una volta all'esterno della modalità di modifica. Questo evento non si verifica se nessuna cella nella riga corrente è stata modificata o se il valore della QuestionEventArgs.Response proprietà è stato impostato su false in un RowDirtyStateNeeded gestore eventi.

    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;
       }
    }
    
    
    
    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 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
    
  9. Implementare un gestore per l'evento UserDeletingRow che elimina un oggetto esistente Customer dall'archivio dati o rimuove un oggetto non salvato Customer che rappresenta una riga appena creata.

    Questo evento si verifica ogni volta che l'utente elimina una riga facendo clic su un'intestazione di riga e premendo il tasto DELETE.

    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;
       }
    }
    
    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;
        }
    }
    
    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
    
  10. Implementare una classe semplice Customers per rappresentare gli elementi di dati usati da questo esempio di codice.

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

Test dell'applicazione

È ora possibile testare il modulo per assicurarsi che si comporti come previsto.

Per testare il modulo

  • Compilare l'applicazione ed eseguirla.

    Verrà visualizzato un DataGridView controllo popolato con tre record dei clienti. È possibile modificare i valori di più celle in una riga e premere ESC due volte in modalità di modifica e una volta fuori dalla modalità di modifica per ripristinare i valori originali dell'intera riga. Quando si modificano, aggiungono o eliminano righe nel controllo, Customer gli oggetti nell'archivio dati vengono modificati, aggiunti o eliminati.

Passaggi successivi

Questa applicazione offre una conoscenza di base degli eventi che è necessario gestire per implementare la modalità virtuale nel DataGridView controllo. È possibile migliorare questa applicazione di base in diversi modi:

  • Implementare un archivio dati che memorizza nella cache i valori di un database esterno. La cache deve recuperare e rimuovere i valori in base alle esigenze, in modo che contenga solo ciò che è necessario per la visualizzazione durante l'utilizzo di una piccola quantità di memoria nel computer client.

  • Ottimizzare le prestazioni dell'archivio dati in base ai requisiti. Ad esempio, è possibile compensare le connessioni di rete lente anziché le limitazioni di memoria del computer client usando dimensioni della cache maggiori e riducendo al minimo il numero di query di database.

Per altre informazioni sulla memorizzazione nella cache dei valori da un database esterno, vedere Procedura: Implementare la modalità virtuale con caricamento dei dati JIT nel controllo DataGridView Windows Form.

Vedi anche