ComboBox 컨트롤을 사용하여 Visual CSharp의 ListView 컨트롤에서 데이터 편집

이 문서에서는 ComboBox 컨트롤을 사용하여 ListView 컨트롤에서 데이터를 편집하는 방법을 보여 줍니다. 이 메서드는 ListView 컨트롤에서 데이터를 편집하는 표준 텍스트 상자 접근 방식을 대체합니다.

원래 제품 버전: Visual C#
원래 KB 번호: 320344

기술에 대한 설명

ListView 컨트롤의 속성을 사용하여 LabelEdit 사용자가 ListView 컨트롤의 내용을 편집하도록 허용할 수 있습니다. ListView 컨트롤에서 데이터를 편집하려면 표준 텍스트 상자를 사용할 수 있습니다. 경우에 따라 컨트롤을 편집하는 다른 컨트롤을 갖는 것이 유용합니다. 이 문서에서는 ListView가 세부 정보 보기에 있을 때 ComboBox 컨트롤을 사용하여 ListView에서 데이터를 편집하는 방법을 시뮬레이션합니다.

사용자가 ListView에서 행을 선택하면 클릭한 행의 첫 번째 열에 대한 경계 사각형을 찾기 위한 계산이 수행됩니다. 이 계산은 행을 클릭할 때와 ComboBox의 크기가 적절하게 조정되고 표시될 때 열이 표시되지 않거나 완전히 표시되지 않을 수 있다는 점을 고려합니다.

이 샘플은 ComboBox의 위치 지정 및 크기 조정 외에도 ListView 컨트롤 WM_VSCROLL 의 두 메시지( 및 )를 감시합니다 WM_HSCROLL. 이러한 메시지는 사용자가 ListView 컨트롤을 세로 또는 가로로 스크롤할 때마다 발생합니다. ComboBox는 실제로 ListView 컨트롤의 일부가 아니므로 ComboBox는 ListView를 사용하여 자동으로 스크롤되지 않습니다. 따라서 이러한 두 메시지 중 하나가 발생할 때마다 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. 도구 상자의 일반 섹션에서 Form1로 MyListView를 끌어옵니다.
  3. 도구 상자의 Windows Forms 섹션에서 Form1로 ComboBox 컨트롤을 끌어옵니다.

  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. 의 이벤트에 다음 코드를 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에서 클릭한 행의 첫 번째 열에 배치됩니다.