Использование элемента управления ComboBox для изменения данных в элементе управления ListView в Visual CSharp

В этой статье показано, как использовать элемент управления ComboBox для редактирования данных в элементе управления ListView. Этот метод заменяет стандартный подход к текстовым полям для редактирования данных в элементе управления ListView.

Исходная версия продукта: Visual C#
Исходный номер базы знаний: 320344

Описание метода

С помощью LabelEdit свойства элемента управления ListView можно разрешить пользователю изменять содержимое элемента управления ListView. Чтобы изменить данные в элементе управления ListView, можно использовать стандартное текстовое поле. Иногда полезно использовать другой элемент управления для редактирования элемента управления. В этой статье имитируется использование элемента управления ComboBox для редактирования данных в ListView, когда ListView находится в представлении Сведений.

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

Помимо позиционирования и изменения размера ComboBox, этот пример также следит за двумя сообщениями в элементе управления ListView: WM_VSCROLL и WM_HSCROLL. Эти сообщения возникают всякий раз, когда пользователь прокручивает элемент управления ListView по вертикали или по горизонтали. Так как comboBox физически не является частью элемента управления ListView, comboBox не прокручивается автоматически с помощью ListView. Поэтому при возникновении любого из этих двух сообщений поле ComboBox должно быть скрыто. Чтобы watch для этих сообщений, создайте пользовательский UserControl класс, наследующий от класса ListView. В этом пользовательском элементе WndProc управления метод переопределяется, чтобы разрешить проверку прокрутки всех сообщений.

Создание унаследованного элемента управления ListView

  1. Запустите Microsoft Visual Studio .NET.

  2. В меню Файл выберите пункт Создать и затем пункт Проект.

  3. В диалоговом окне Новый проект выберите Пункт Проекты Visual C# в разделе Типы проектов, а затем выберите Библиотека элементов управления Windows в разделе Шаблоны.

  4. Замените весь код в UserControl классе следующим кодом:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Windows.Forms;
    
    namespace InheritedListView
    {
        /// <summary>
        /// Summary description for UserControl1.
        /// </summary>
        public class MyListView : System.Windows.Forms.ListView
        {
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;
    
            public MyListView()
            {
                // This call is required by the Windows.Forms Form Designer.
                InitializeComponent();
                // TODO: Add any initialization after the InitForm call
            }
    
            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (components != null)
                        components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Component Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                components = new System.ComponentModel.Container();
            }
            #endregion
    
            private const int WM_HSCROLL = 0x114;
            private const int WM_VSCROLL = 0x115;
    
            protected override void WndProc(ref Message msg)
            {
                // Look for the WM_VSCROLL or the WM_HSCROLL messages.
                if ((msg.Msg == WM_VSCROLL) || (msg.Msg == WM_HSCROLL))
                {
                    // Move focus to the ListView to cause ComboBox to lose focus.
                    this.Focus();
                }
    
                // Pass message to default handler.
                base.WndProc(ref msg);
            }
        }
    }
    
  5. Сохраните изменения и выполните построение проекта.

Создание примера приложения

  1. Чтобы создать новое приложение Windows в Visual C# .NET, выполните следующие действия:

    1. В меню Файл выберите пункт Создать и затем пункт Проект.
    2. В диалоговом окне Новый проект щелкните Проекты Visual C# в разделе Типы проектов, а затем выберите Приложение Windows в разделе Шаблоны. По умолчанию создается Form1.
  2. Чтобы добавить элемент управления, созданный в разделе Создание унаследованного элемента управления ListView , в приложение Windows выполните следующие действия.

    1. В меню Сервис выберите пункт Настроить панель элементов.
    2. На вкладке компоненты платформа .NET Framework нажмите кнопку Обзор.
    3. В диалоговом окне Открыть найдите элемент управления, созданный в разделе Создание унаследованного элемента управления ListView , и нажмите кнопку Открыть. Он добавляет этот элемент управления на панель элементов, чтобы его можно было использовать аналогично любому другому элементу управления.
    4. Перетащите MyListView из раздела Общие панели элементов в Form1.
  3. Перетащите элемент управления ComboBox из раздела Windows Forms панели элементов в Form1.

  4. В окне Свойства comboBox измените свойство Name на cbListViewCombo, а затем задайте для свойства Visible значение False.

  5. Добавьте следующий код в класс Form1 над конструктором:

    private ListViewItem lvItem;
    
  6. Добавьте следующий код в Load событие Form1:

    // Add a few items to the combo box list.
    this.cbListViewCombo.Items.Add("NC");
    this.cbListViewCombo.Items.Add("WA");
    
    // Set view of ListView to Details.
    this.myListView1.View = View.Details;
    
    // Turn on full row select.
    this.myListView1.FullRowSelect = true;
    
    // Add data to the ListView.
    ColumnHeader columnheader;
    ListViewItem listviewitem;
    
    // Create sample ListView data.
    listviewitem = new ListViewItem("NC");
    listviewitem.SubItems.Add("North Carolina");
    this.myListView1.Items.Add(listviewitem);
    
    listviewitem = new ListViewItem("WA");
    listviewitem.SubItems.Add("Washington");
    this.myListView1.Items.Add(listviewitem);
    
    // Create column headers for the data.
    columnheader = new ColumnHeader();
    columnheader.Text = "State Abbr.";
    this.myListView1.Columns.Add(columnheader);
    
    columnheader = new ColumnHeader();
    columnheader.Text = "State";
    this.myListView1.Columns.Add(columnheader);
    
    // Loop through and size each column header to fit the column header text.
    foreach (ColumnHeader ch in this.myListView1.Columns)
    {
       ch.Width = -2;
    }
    
  7. Добавьте следующий код в SelectedValueChanged событие ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  8. Добавьте следующий код в Leave событие ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  9. Добавьте следующий код в KeyPress событие ComboBox:

    // Verify that the user presses ESC.
    switch (e.KeyChar)
    {
       case (char)(int)Keys.Escape:
       {
          // Reset the original text value, and then hide the ComboBox.
          this.cbListViewCombo.Text = lvItem.Text;
          this.cbListViewCombo.Visible = false;
          break;
       }
    
       case (char)(int)Keys.Enter:
       {
          // Hide the ComboBox.
          this.cbListViewCombo.Visible = false;
          break;
       }
    }
    
  10. Добавьте следующий код в MouseUp событие myListView1:

    // Get the item on the row that is clicked.
    lvItem = this.myListView1.GetItemAt(e.X, e.Y);
    
    // Make sure that an item is clicked.
    if (lvItem != null)
    {
        // Get the bounds of the item that is clicked.
        Rectangle ClickedItem = lvItem.Bounds;
    
        // Verify that the column is completely scrolled off to the left.
        if ((ClickedItem.Left + this.myListView1.Columns[0].Width) < 0)
        {
            // If the cell is out of view to the left, do nothing.
            return;
        }
    
        // Verify that the column is partially scrolled off to the left.
        else if (ClickedItem.Left < 0)
        {
            // Determine if column extends beyond right side of ListView.
            if ((ClickedItem.Left + this.myListView1.Columns[0].Width) > this.myListView1.Width)
            {
                // Set width of column to match width of ListView.
                ClickedItem.Width = this.myListView1.Width;
                ClickedItem.X = 0;
            }
            else
            {
                // Right side of cell is in view.
                ClickedItem.Width = this.myListView1.Columns[0].Width + ClickedItem.Left;
                ClickedItem.X = 2;
            }
        }
        else if (this.myListView1.Columns[0].Width > this.myListView1.Width)
        {
            ClickedItem.Width = this.myListView1.Width;
        }
        else
        {
            ClickedItem.Width = this.myListView1.Columns[0].Width;
            ClickedItem.X = 2;
        }
    
        // Adjust the top to account for the location of the ListView.
        ClickedItem.Y += this.myListView1.Top;
        ClickedItem.X += this.myListView1.Left;
    
        // Assign calculated bounds to the ComboBox.
        this.cbListViewCombo.Bounds = ClickedItem;
    
        // Set default text for ComboBox to match the item that is clicked.
        this.cbListViewCombo.Text = lvItem.Text;
    
        // Display the ComboBox, and make sure that it is on top with focus.
        this.cbListViewCombo.Visible = true;
        this.cbListViewCombo.BringToFront();
        this.cbListViewCombo.Focus();
    }
    

Убедитесь, что он работает

  1. Сохраните и запустите пример.

  2. Щелкните строку в ListView.

    Примечание.

    Над расположением первого столбца текущей строки появится поле со списком.

  3. Чтобы скрыть поле со списком, щелкните элемент в поле со списком, нажмите клавишу ESC, а затем прокрутите listView или щелкните другой элемент управления.

    Примечание.

    Значение, выбранное в поле со списком, помещается в первый столбец щелкнутой строки ListView.