Show / Hide Table of Contents

Пошаговое руководство. Реализация виртуального режима для элемента управления DataGridView в Windows Forms

Если вы хотите отобразить очень большому количеству табличные данные в DataGridView элемента управления, можно задать VirtualMode свойства true и явно управлять взаимодействием элемента управления с хранилищем данных. Это позволяет оптимизировать производительность элемента управления в этой ситуации.

DataGridView Управления предусмотрено несколько событий, которые можно обрабатывать для взаимодействия с хранилищем пользовательских данных. В этом пошаговом руководстве поможет выполнить процесс реализации этих обработчиков событий. В примере кода в этом разделе используется очень простой источник данных для иллюстрации. На практике, обычно загружаются только те строки, необходимые для отображения в кэше и обрабатывать DataGridView события для взаимодействия с кэшем и его обновления. Дополнительные сведения см. в разделе реализация виртуального режима с JIT-загрузкой данных в элементе управления DataGridView Windows Forms

Чтобы скопировать код из этого раздела единым блоком, см. раздел Практическое руководство. Реализация виртуального режима в Windows Forms элемента управления DataGridView.

Создание формы

Реализация виртуального режима

  1. Создайте класс, производный от Form и содержит DataGridView элемента управления.

    Следующий код содержит некоторые основные инициализации. Он объявляется несколько переменных, которые будут использоваться на последующих этапах, предоставляет Main метод и предоставляет простой макет формы в конструкторе класса.

    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)";
        }
    
    }
    
  2. Реализовать обработчик для формы Load событие, которое инициализирует DataGridView управления и заполняет хранилище данных с помощью образцов значений.

    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;
    }
    
  3. Реализовать обработчик для CellValueNeeded событие, которое извлекает запрошенное значение ячейки из хранилища данных или Customer объекта, находящегося в режиме редактирования.

    Это событие возникает каждый раз, когда DataGridView элемента управления требуется прорисовать ячейку.

    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;
        }
    }
    
  4. Реализовать обработчик для CellValuePushed события, которое сохраняет измененное значение ячейки в Customer объект, представляющий редактируемой строки. Это событие возникает каждый раз, когда пользователь фиксирует изменение значения ячейки.

    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;
        }
    }
    
  5. Реализовать обработчик для NewRowNeeded событие, которое создает новый Customer объект, представляющий только что созданной строки.

    Это событие возникает каждый раз, когда пользователь вводит строку для новых записей.

    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;
    }
    
  6. Реализовать обработчик для RowValidated событие, которое сохраняет новые или измененные строки в хранилище данных.

    Это событие возникает каждый раз, когда пользователь изменяет текущую строку.

    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;
        }
    }
    
  7. Реализовать обработчик для RowDirtyStateNeeded событие, указывающее, является ли CancelRowEdit событие произойдет в том случае, если пользователь восстанавливает строку, нажав клавишу ESC, дважды в режиме редактирования или один раз в другом режиме.

    По умолчанию CancelRowEdit происходит при восстановлении строки, если ни одной из ячеек в текущей строке были изменены, если не QuestionEventArgs.Response свойству true в RowDirtyStateNeeded обработчик событий. Это событие полезно в тех случаях, когда область фиксации определяется во время выполнения.

    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;
        }
    }
    
  8. Реализовать обработчик для CancelRowEdit событий, который удаляет значения Customer объект, представляющий текущую строку.

    Это событие происходит, если пользователь восстанавливает строку, нажав клавишу ESC, дважды в режиме редактирования или один раз в другом режиме. Это событие не происходит, если ячейки отсутствуют в текущей строке были изменены или если значение QuestionEventArgs.Response было присвоено свойство false в RowDirtyStateNeeded обработчик событий.

    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;
        }
    }
    
  9. Реализовать обработчик для UserDeletingRow событие, которое удаляет существующий Customer объекта из хранилища данных или отменяет несохраненный Customer объект, представляющий только что созданной строки.

    Это событие возникает каждый раз, когда пользователь удаляет строку, при щелчке заголовка строки и нажав клавишу DELETE.

    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;
        }
    }
    
  10. Реализовать простой Customers класс для представления элементов данных, используемых в этом примере кода.

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

Тестирование приложения

Теперь можно проверить форму, чтобы убедиться, что она правильно работает.

Чтобы проверить форму

  • Скомпилируйте и запустите приложение.

    Вы увидите DataGridView управления с тремя записями клиентов. Можно изменить значения нескольких ячеек в строке и нажмите клавишу ESC, дважды в режиме редактирования и один раз за пределами режим редактирования, чтобы вернуть всю строку к исходным значениям. Когда изменения, добавления или удаления строк в элементе управления Customer объектов в хранилище данных будут изменены, добавлены или удалены.

Следующие шаги

Это приложение позволяет основные события, необходимо обработать для реализации виртуального режима в DataGridView элемента управления. Вы можете улучшить это основное приложение несколькими способами:

  • Реализуйте хранилище данных, которое кэширует значения из внешней базы данных. Кэш извлекает и отменяет по необходимости, чтобы он содержал только необходимые для отображения при использовании небольшой объем памяти на клиентском компьютере.

  • Оптимизировать производительность хранилища данных в зависимости от требований. Например можно компенсировать медленные сетевые подключения, а не ограничения памяти клиентского компьютера с помощью большего размера кэша, сводя к минимуму число запросов к базе данных.

Дополнительные сведения о кэшировании значений из внешней базы данных, см. в разделе как: Реализация виртуального режима с JIT в загрузкой данных в Windows Forms элемента управления DataGridView.

См. также

  • DataGridView
  • VirtualMode
  • CellValueNeeded
  • CellValuePushed
  • NewRowNeeded
  • RowValidated
  • RowDirtyStateNeeded
  • CancelRowEdit
  • UserDeletingRow
  • Оптимизация производительности элемента управления DataGridView в Windows Forms
  • Масштабирование элемента управления DataGridView в Windows Forms
  • Реализация виртуального режима с JIT-загрузкой данных для элемента управления DataGridView в Windows Forms
  • Практическое руководство. Реализация виртуального режима для элемента управления DataGridView в Windows Forms
Back to top Неофициальная документация по .NET на русском языке. Лицензия: CC-BY 4.0. Основано на документации по .NET с Microsoft Docs
Generated by DocFX