Usare un controllo ComboBox per modificare i dati in un controllo ListView in Visual CSharp

Questo articolo illustra come usare un controllo ComboBox per modificare i dati in un controllo ListView. Questo metodo sostituisce l'approccio della casella di testo standard per la modifica dei dati in un controllo ListView.

Versione originale del prodotto: Oggetto visivo C#
Numero KB originale: 320344

Descrizione della tecnica

Usando la LabelEdit proprietà del controllo ListView, è possibile consentire all'utente di modificare il contenuto del controllo ListView. Per modificare i dati nel controllo ListView, è possibile usare una casella di testo standard. Occasionalmente, è utile avere un altro controllo per modificare il controllo. Questo articolo simula come usare un controllo ComboBox per modificare i dati in un controllo ListView quando ListView è in visualizzazione Dettagli.

Quando l'utente seleziona una riga in ListView, viene eseguito un calcolo per individuare il rettangolo di delimitazione per la prima colonna della riga su cui si fa clic. Tale calcolo tiene conto del fatto che la colonna potrebbe non essere visibile o non essere completamente visibile quando si fa clic sulla riga e quando il controllo ComboBox viene ridimensionato e visualizzato in modo appropriato.

Oltre a posizionare e ridimensionare ComboBox, questo esempio controlla anche due messaggi nel controllo ListView: WM_VSCROLL e WM_HSCROLL. Questi messaggi si verificano ogni volta che l'utente scorre il controllo ListView verticalmente o orizzontalmente. Poiché ComboBox non fa fisicamente parte del controllo ListView, combobox non scorre automaticamente con ListView. Pertanto, ogni volta che si verifica uno di questi due messaggi, il controllo ComboBox deve essere nascosto. Per watch per questi messaggi, si crea una classe personalizzata UserControl che eredita dalla classe ListView. In questo controllo personalizzato viene eseguito l'override del WndProc metodo per consentire la verifica dello scorrimento di tutti i messaggi.

Creare il controllo ListView ereditato

  1. Avviare Microsoft Visual Studio .NET.

  2. Scegliere Nuovo dal menu File, quindi fare clic su Progetto.

  3. Nella finestra di dialogo Nuovo progetto fare clic su Progetti Visual C# in Tipi di progetto e quindi fare clic su Libreria di controlli di Windows in Modelli.

  4. Sostituire tutto il codice nella UserControl classe con il codice seguente:

    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. Salvare e compilare il progetto.

Creare l'applicazione di esempio

  1. Seguire questa procedura per creare una nuova applicazione Windows in Visual C# .NET:

    1. Scegliere Nuovo dal menu File, quindi fare clic su Progetto.
    2. Nella finestra di dialogo Nuovo progetto fare clic su Progetti Visual C# in Tipi di progetto e quindi su Applicazione Windows in Modelli. Per impostazione predefinita, viene creato Form1.
  2. Seguire questa procedura per aggiungere il controllo creato nella sezione Creare il controllo ListView ereditato all'applicazione Windows:

    1. Scegliere Personalizza casella degli strumenti dal menu Strumenti.
    2. Nella scheda Componenti di .NET Framework fare clic su Sfoglia.
    3. Nella finestra di dialogo Apri individuare il controllo creato nella sezione Crea il controllo ListView ereditato e quindi fare clic su Apri. Questo controllo viene aggiunto alla casella degli strumenti in modo che sia possibile usare il controllo in modo analogo a qualsiasi altro controllo.
    4. Trascinare MyListView dalla sezione Generale della casella degli strumenti a Form1.
  3. Trascinare un controllo ComboBox dalla sezione Windows Forms della casella degli strumenti a Form1.

  4. Nella finestra Proprietà di ComboBox modificare la proprietà Name in cbListViewCombo e quindi impostare la proprietà Visiblesu False.

  5. Aggiungere il codice seguente alla classe di Form1 sopra il costruttore:

    private ListViewItem lvItem;
    
  6. Aggiungere il codice seguente all'evento Load di 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. Aggiungere il codice seguente all'evento SelectedValueChanged di ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  8. Aggiungere il codice seguente all'evento Leave di ComboBox:

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  9. Aggiungere il codice seguente all'evento KeyPress di 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. Aggiungere il codice seguente all'evento MouseUp di 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();
    }
    

Verificare che funzioni

  1. Salvare ed eseguire l'esempio.

  2. Fare clic su una riga in ListView.

    Nota

    Viene visualizzata una casella combinata sulla posizione della prima colonna della riga corrente.

  3. Per nascondere la casella combinata, fare clic su un elemento nella casella combinata, premere ESC e quindi scorrere listView o fare clic su un altro controllo.

    Nota

    Il valore su cui è stato fatto clic nella casella combinata viene inserito nella prima colonna della riga selezionata di ListView.