Utiliser un contrôle ComboBox pour modifier des données dans un contrôle ListView dans Visual CSharp

Cet article explique comment utiliser un contrôle ComboBox pour modifier les données d’un contrôle ListView. Cette méthode remplace l’approche de zone de texte standard qui consiste à modifier les données dans un contrôle ListView.

Version d’origine du produit : Visual C#
Numéro de la base de connaissances d’origine : 320344

Description de la technique

En utilisant la LabelEdit propriété du contrôle ListView, vous pouvez autoriser l’utilisateur à modifier le contenu du contrôle ListView. Pour modifier les données dans le contrôle ListView, vous pouvez utiliser une zone de texte standard. Parfois, il est utile d’avoir un autre contrôle pour modifier le contrôle. Cet article simule l’utilisation d’un contrôle ComboBox pour modifier les données d’un contrôle ListView lorsque le contrôle ListView est en mode Détails.

Lorsque l’utilisateur sélectionne une ligne dans listView, un calcul est effectué pour localiser le rectangle englobant de la première colonne de la ligne sur laquelle on clique. Ce calcul tient compte du fait que la colonne peut ne pas être visible ou ne pas être entièrement visible lorsque l’utilisateur clique sur la ligne et que la zone combobox est dimensionnée et affichée de manière appropriée.

Outre le positionnement et le dimensionnement de comboBox, cet exemple surveille également deux messages sur le contrôle ListView : WM_VSCROLL et WM_HSCROLL. Ces messages se produisent chaque fois que l’utilisateur fait défiler le contrôle ListView verticalement ou horizontalement. Étant donné que comboBox ne fait pas physiquement partie du contrôle ListView, le contrôle ComboBox ne défile pas automatiquement avec le Contrôle ListView. Par conséquent, chaque fois que l’un de ces deux messages se produit, le ComboBox doit être masqué. Pour watch pour ces messages, vous créez une classe personnalisée UserControl qui hérite de la classe ListView. Dans ce contrôle personnalisé, la WndProc méthode est remplacée pour permettre à tous les messages d’être vérifiés pour le défilement.

Créer le contrôle ListView hérité

  1. Démarrez Microsoft Visual Studio .NET.

  2. On the File menu, point to New, and then click Project.

  3. Dans la boîte de dialogue Nouveau projet , cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur Bibliothèque de contrôles Windows sous Modèles.

  4. Remplacez tout le code de la UserControl classe par le code suivant :

    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. Enregistrez et générez le projet.

Créer l’exemple d’application

  1. Procédez comme suit pour créer une application Windows dans Visual C# .NET :

    1. On the File menu, point to New, and then click Project.
    2. Dans la boîte de dialogue Nouveau projet , cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur Application Windows sous Modèles. Par défaut, Form1 est créé.
  2. Procédez comme suit pour ajouter le contrôle que vous avez créé dans la section Créer le contrôle ListView hérité à votre application Windows :

    1. Dans le menu Outils , cliquez sur Personnaliser la boîte à outils.
    2. Sous l’onglet Composants .NET Framework , cliquez sur Parcourir.
    3. Dans la boîte de dialogue Ouvrir , recherchez le contrôle que vous avez créé dans la section Créer le contrôle ListView hérité , puis cliquez sur Ouvrir. Il ajoute ce contrôle à la boîte à outils afin que vous puissiez utiliser le contrôle de la même façon que n’importe quel autre contrôle.
    4. Faites glisser MyListView de la section Général de la boîte à outils vers Form1.
  3. Faites glisser un contrôle ComboBox de la section Windows Forms de la boîte à outils vers Form1.

  4. Dans la fenêtre Propriétés de ComboBox, remplacez la propriété Name par cbListViewCombo, puis définissez la propriété Visible sur False.

  5. Ajoutez le code suivant à la classe de Form1 au-dessus du constructeur :

    private ListViewItem lvItem;
    
  6. Ajoutez le code suivant à l’événement Load de 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. Ajoutez le code suivant à l’événement SelectedValueChanged de comboBox :

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  8. Ajoutez le code suivant à l’événement Leave de comboBox :

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  9. Ajoutez le code suivant à l’événement KeyPress de 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. Ajoutez le code suivant à l’événement MouseUp 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();
    }
    

Vérifier que cela fonctionne

  1. Enregistrez et exécutez l’exemple.

  2. Cliquez sur une ligne dans listView.

    Remarque

    Une zone de liste déroulante s’affiche sur l’emplacement de la première colonne de la ligne actuelle.

  3. Pour masquer la zone de liste déroulante, cliquez sur un élément de la zone de liste modifiable, appuyez sur Échap, puis faites défiler le contrôle ListView ou cliquez sur un autre contrôle.

    Remarque

    La valeur sur laquelle vous avez cliqué dans la zone de liste déroulante est placée dans la première colonne de la ligne de l’objet ListView.