ComboBox コントロールを使用して、Visual CSharp の ListView コントロール内のデータを編集する

この記事では、ComboBox コントロールを使用して ListView コントロール内のデータを編集する方法について説明します。 このメソッドは、ListView コントロール内のデータを編集する標準的なテキスト ボックス アプローチに置き換えられます。

元の製品バージョン: Visual C#
元の KB 番号: 320344

手法の説明

ListView コントロールの プロパティを使用 LabelEdit すると、ユーザーが ListView コントロールの内容を編集できるようになります。 ListView コントロールのデータを編集するには、標準のテキスト ボックスを使用します。 場合によっては、コントロールを編集する別のコントロールを用意すると便利です。 この記事では、ListView が詳細ビューにあるときに ComboBox コントロールを使用して ListView 内のデータを編集する方法をシミュレートします。

ユーザーが ListView で行を選択すると、クリックされた行の最初の列の外接する四角形を検索する計算が実行されます。 この計算では、行がクリックされたとき、および ComboBox のサイズが適切に設定され、表示されるときに、列が表示されないか、完全に表示されない可能性があることを考慮します。

このサンプルでは、ComboBox の配置とサイズ設定に加えて、ListView コントロール WM_VSCROLLWM_HSCROLLの 2 つのメッセージも監視します。 これらのメッセージは、ユーザーが ListView コントロールを垂直方向または水平方向にスクロールするたびに発生します。 ComboBox は ListView コントロールに物理的に含まれていないため、ComboBox は ListView と共に自動的にスクロールしません。 したがって、これら 2 つのメッセージのいずれかが発生するたびに、ComboBox は非表示にする必要があります。 これらのメッセージをwatchするには、ListView クラスから継承するカスタム UserControl クラスを作成します。 このカスタム コントロールでは、 メソッドがオーバーライドされ、 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. Visual C# .NET で新しい Windows アプリケーションを作成するには、次の手順に従います。

    1. [ ファイル] メニューの [ 新規] をポイントし、[ プロジェクト] をクリックします。
    2. [新しいプロジェクト] ダイアログ ボックスで、[プロジェクトの種類] の [Visual C# プロジェクト] をクリックし、[テンプレート] の [Windows アプリケーション] をクリックします。 既定では、Form1 が作成されます。
  2. [ 継承された ListView コントロールの作成] セクションで作成したコントロールを Windows アプリケーションに追加するには、次の手順に従います。

    1. [ ツール ] メニューの [ ツールボックスのカスタマイズ] をクリックします。
    2. [.NET Framework コンポーネント] タブで、[参照] をクリックします。
    3. [ 開く ] ダイアログ ボックスの [ 継承された ListView コントロールの作成 ] セクションで作成したコントロールを見つけて、[ 開く] をクリックします。 このコントロールをツールボックスに追加して、他のコントロールと同様にコントロールを使用できるようにします。
    4. ツールボックスの [全般 ] セクションから [フォーム 1] に MyListView をドラッグします。
  3. ComboBox コントロールをツールボックスの [Windows フォーム] セクションから Form1 にドラッグします。

  4. ComboBox の [プロパティ ] ウィンドウで、 Name プロパティを cbListViewCombo に変更し、 Visible プロパティを False に設定 します

  5. コンストラクターの上の クラスに次の Form1 コードを追加します。

    private ListViewItem lvItem;
    
  6. Form1 のイベントに次のコードを Load 追加します。

    // 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. ComboBox のイベントに SelectedValueChanged 次のコードを追加します。

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  8. ComboBox のイベントに Leave 次のコードを追加します。

    // Set text of ListView item to match the ComboBox.
    lvItem.Text = this.cbListViewCombo.Text;
    
    // Hide the ComboBox.
    this.cbListViewCombo.Visible = false;
    
  9. ComboBox のイベントに KeyPress 次のコードを追加します。

    // 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. のイベントに次のmyListView1コードをMouseUp追加します。

    // 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 のクリックされた行の最初の列に配置されます。