首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# ListView 嵌入 ComboBox:點擊儲存格顯示下拉選單編輯

     編輯:關於C#

WinForms ListView(Details 檢視)預設不支援儲存格內編輯。本文示範繼承 ListView 攔截滾動訊息、搭配獨立 ComboBox 控制項,在使用者點擊第一欄時精準定位並顯示下拉選單,選取後寫回儲存格並隱藏。

核心元件

  1. MyListView:繼承 ListView,覆寫 WndProc 攔截 WM_VSCROLL/WM_HSCROLL,捲動時將焦點移回 ListView 觸發 ComboBox 失焦隱藏。
  2. Form1:包含 MyListView 與隱藏的 ComboBox(Visible=false)。

關鍵程式碼片段

MyListView 攔截捲動


public class MyListView : ListView
{
    private const int WM_HSCROLL = 0x114;
    private const int WM_VSCROLL = 0x115;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_VSCROLL || m.Msg == WM_HSCROLL)
            this.Focus(); // 強制 ComboBox 失焦
        base.WndProc(ref m);
    }
}

Form1 滑鼠點擊定位與顯示 ComboBox


private ListViewItem _clickedItem;

private void myListView1_MouseUp(object sender, MouseEventArgs e)
{
    _clickedItem = myListView1.GetItemAt(e.X, e.Y);
    if (_clickedItem == null) return;

    // 僅第一欄可編輯
    if (e.X > myListView1.Columns[0].Width) return;

    Rectangle bounds = _clickedItem.Bounds;
    // 處理水平捲動導致欄位部分可見的情況
    if (bounds.Left < 0) { /* 計算可見寬度、調整 X */ }
    // 垂直位置加上 ListView.Top
    bounds.Y += myListView1.Top;
    bounds.X += myListView1.Left;

    cbListViewCombo.Bounds = bounds;
    cbListViewCombo.Text = _clickedItem.Text;
    cbListViewCombo.Visible = true;
    cbListViewCombo.BringToFront();
    cbListViewCombo.Focus();
}

ComboBox 事件處理


private void cbListViewCombo_SelectedIndexChanged(object sender, EventArgs e)
{
    _clickedItem.Text = cbListViewCombo.Text;
    cbListViewCombo.Visible = false;
}

private void cbListViewCombo_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == (char)Keys.Escape)
    {
        cbListViewCombo.Text = _clickedItem.Text; // 還原
        cbListViewCombo.Visible = false;
    }
    else if (e.KeyChar == (char)Keys.Enter)
        cbListViewCombo.Visible = false;
}

private void myListView1_Click(object sender, EventArgs e)
    => cbListViewCombo.Visible = false; // 點擊其他處隱藏

關鍵技術細節

挑戰解決方案
水平捲動時第一欄部分隱藏計算 bounds.Left、bounds.Width 修正 ComboBox.Bounds
垂直捲動時 ComboBox 位置錯位bounds.Y += listView.Top 轉換為表單座標
捲動時 ComboBox 残留MyListView.WndProc 攔截 WM_VSCROLL/WM_HSCROLL 呼叫 Focus()
鍵盤 Esc 取消編輯KeyPress 捕捉 Keys.Escape 還原文字並隱藏

擴充建議

  • 支援多欄編輯:依 e.X 判斷欄位索引,顯示不同編輯控制項(DateTimePicker、TextBox、NumericUpDown)。
  • 資料繫結:ComboBox.DataSource 綁定列表,DisplayMember/ValueMember 分離顯示與實值。
  • 驗證:Validating 事件檢查輸入合法性,不合法時 e.Cancel = true 保持編輯狀態。
  • 完整編輯框架:參考 ObjectListView (開源) 或自行實作 IEmbeddedEditor 介面統一管理。

替代方案

  • DataGridView:內建 DataGridViewComboBoxColumn、編輯模式、資料繫結、虛擬模式,功能完整得多,新專案優先考慮。
  • ObjectListView:開源 ListView 增強庫,支援單元格編輯、排序、過濾、分組。

此技巧適合「必須用 ListView、僅需簡單下拉編輯」的舊專案維護場景;新專案請直接使用 DataGridView。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved