Usar um controle ComboBox para editar dados em um controle ListView no Visual CSharp

Este artigo demonstra como usar um controle ComboBox para editar os dados em um controle ListView. Esse método substitui a abordagem da caixa de texto padrão de edição dos dados em um controle ListView.

Versão original do produto: Visual C#
Número de KB original: 320344

Descrição da técnica

Usando a LabelEdit propriedade do controle ListView, você pode permitir que o usuário edite o conteúdo do controle ListView. Para editar os dados no controle ListView, você pode usar uma caixa de texto padrão. Ocasionalmente, é útil ter outro controle para editar o controle. Este artigo simula como usar um controle ComboBox para editar os dados em um ListView quando o ListView estiver na exibição Detalhes.

Quando o usuário seleciona uma linha no ListView, um cálculo é feito para localizar o retângulo delimitador para a primeira coluna da linha clicada. Esse cálculo leva em conta que a coluna pode não estar visível ou pode não estar totalmente visível quando a linha é clicada e quando o ComboBox é dimensionado e exibido adequadamente.

Além de posicionar e dimensionar o ComboBox, este exemplo também observa duas mensagens no controle ListView: WM_VSCROLL e WM_HSCROLL. Essas mensagens ocorrem sempre que o usuário percorre o controle ListView vertical ou horizontalmente. Como o ComboBox não faz parte fisicamente do controle ListView, o ComboBox não rola automaticamente com o ListView. Portanto, sempre que uma dessas duas mensagens ocorrer, o ComboBox deve estar oculto. Para watch para essas mensagens, crie uma classe personalizada UserControl herdada da classe ListView. Neste controle personalizado, o WndProc método é substituído para permitir que todas as mensagens sejam verificadas para rolagem.

Criar o controle ListView herdado

  1. Inicie o Microsoft Visual Studio .NET.

  2. No menu arquivo, aponte para novo e, em seguida, clique em Project.

  3. Na caixa de diálogo Novo Projeto , clique em Projetos do Visual C# em Tipos de Projeto e clique em Biblioteca de Controle do Windows em Modelos.

  4. Substitua todo o código da UserControl classe pelo seguinte código:

    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. Salve e crie o projeto.

Criar o aplicativo de exemplo

  1. Siga estas etapas para criar um novo aplicativo Windows no Visual C# .NET:

    1. No menu arquivo, aponte para novo e, em seguida, clique em Project.
    2. Na caixa de diálogo Novo Projeto , clique em Projetos do Visual C# em Tipos de Projeto e clique em Aplicativo windows em Modelos. Por padrão, o Form1 é criado.
  2. Siga estas etapas para adicionar o controle que você criou na seção Criar o controle ListView herdado ao seu aplicativo Windows:

    1. No menu Ferramentas , clique em Personalizar Caixa de Ferramentas.
    2. Na guia Componentes .NET Framework, clique em Procurar.
    3. Na caixa de diálogo Abrir , localize o controle que você criou na seção Criar o controle ListView herdado e clique em Abrir. Ele adiciona esse controle à caixa de ferramentas para que você possa usar o controle de forma semelhante a qualquer outro controle.
    4. Arraste MyListView da seção Geral da caixa de ferramentas para o Form1.
  3. Arraste um controle ComboBox da seção Windows Forms da caixa de ferramentas para o Form1.

  4. Na janela Propriedades do ComboBox, altere a propriedade Name para cbListViewCombo e defina a propriedade Visible como False.

  5. Adicione o seguinte código à classe de acima do Form1 construtor:

    private ListViewItem lvItem;
    
  6. Adicione o seguinte código ao Load evento do 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. Adicione o seguinte código ao SelectedValueChanged evento do ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  8. Adicione o seguinte código ao Leave evento do ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  9. Adicione o seguinte código ao KeyPress evento do 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. Adicione o seguinte código ao MouseUp evento de 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();
    }
    

Verificar se ele funciona

  1. Salve e execute o exemplo.

  2. Clique em uma linha no ListView.

    Observação

    Uma caixa de combinação é exibida sobre o local da primeira coluna da linha atual.

  3. Para ocultar a caixa de combinação, clique em um item na caixa de combinação, pressione ESC e role pela ListView ou clique em outro controle.

    Observação

    O valor que você clicou na caixa de combinação é colocado na primeira coluna da linha clicada do ListView.