[C#]ListBox如何偵測Item的新增、插入、與刪除

有時候我們使用ListBox元件會想要針對Item的新增、插入、與刪除做些反應,可能像是有個Item插入時我們會想把游標移到最下面之類的。但內建的ListBox並未將這樣的訊息開放出來,所以我們無法直接的去做這樣的處理,必須要自行去接收視窗訊息才行。

我們可以建立個控制項,繼承自ListBox,並視需要來接收想要處理的視窗訊息。像是想要偵測Item新增的話我們可以偵測LB_ADDSTRING、想要偵測Item插入的話可以偵測LB_INSERTSTRING、想要偵測Item刪除的話可以偵測LB_DELETESTRING。

            private const int LB_ADDSTRING = 0x180;
private const int LB_INSERTSTRING = 0x181;
private const int LB_DELETESTRING = 0x182;


偵測時需覆寫WndProc方法,並在方法內判斷Msg是否是我們所感興趣的訊息。有的訊息會內含較為詳細的資訊,像是Item的索引與值,若有需要可從wparam與lparam中擷取。

            protected override void WndProc(ref Message m)
{
var itemIndex = 0;
var itemValue = string.Empty;

switch (m.Msg)
{
case LB_ADDSTRING:
itemValue = Marshal.PtrToStringUni(m.LParam);
OnItemAdded(EventArgs.Empty);
break;
case LB_INSERTSTRING:
itemIndex = (int)m.WParam;
itemValue = Marshal.PtrToStringUni(m.LParam);
OnItemInserted(EventArgs.Empty);
break;
case LB_DELETESTRING:
itemIndex = (int)m.WParam;
OnItemDeleted(EventArgs.Empty);
break;
default:
break;
}
base.WndProc(ref m);
}

這邊附上較為完整的測試範例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
class ListBoxEx : ListBox
{
#region Const
private const int LB_ADDSTRING = 0x180;
private const int LB_INSERTSTRING = 0x181;
private const int LB_DELETESTRING = 0x182;
#endregion


#region Event
public event EventHandler ItemAdded;
public event EventHandler ItemInserted;
public event EventHandler ItemDeleted;
#endregion


#region Protected Method
protected void OnItemAdded(EventArgs e)
{
if (ItemAdded == null)
return;
ItemAdded(this, e);
}

protected void OnItemInserted(EventArgs e)
{
if (ItemInserted == null)
return;
ItemInserted(this, e);
}

protected void OnItemDeleted(EventArgs e)
{
if (ItemDeleted == null)
return;
ItemDeleted(this, e);
}

protected override void WndProc(ref Message m)
{
var itemIndex = 0;
var itemValue = string.Empty;

switch (m.Msg)
{
case LB_ADDSTRING:
itemValue = Marshal.PtrToStringUni(m.LParam);
OnItemAdded(EventArgs.Empty);
break;
case LB_INSERTSTRING:
itemIndex = (int)m.WParam;
itemValue = Marshal.PtrToStringUni(m.LParam);
OnItemInserted(EventArgs.Empty);
break;
case LB_DELETESTRING:
itemIndex = (int)m.WParam;
OnItemDeleted(EventArgs.Empty);
break;
default:
break;
}
base.WndProc(ref m);
}
#endregion
}

#region Var
private ListBoxEx _listBox;
#endregion


#region Private Property
private ListBoxEx m_ListBox
{
get
{
return _listBox ?? (_listBox = new ListBoxEx()
{
Dock = DockStyle.Fill
});
}
}
#endregion


#region Constructor
public Form1()
{
InitializeComponent();

m_ListBox.ItemAdded += m_ListBox_ItemAdded;
m_ListBox.ItemDeleted += m_ListBox_ItemDeleted;
m_ListBox.ItemInserted += m_ListBox_ItemInserted;

this.panel1.Controls.Add(m_ListBox);
}
#endregion


#region Event Process
private void button1_Click(object sender, EventArgs e)
{
m_ListBox.Items.Add(Guid.NewGuid().ToString());
}

private void button2_Click(object sender, EventArgs e)
{
var index = m_ListBox.SelectedIndex >= 0 ? m_ListBox.SelectedIndex : 0;
m_ListBox.Items.Insert(index, Guid.NewGuid().ToString());
}

private void button3_Click(object sender, EventArgs e)
{
if (m_ListBox.SelectedIndex == -1)
return;
m_ListBox.Items.RemoveAt(m_ListBox.SelectedIndex);
}

void m_ListBox_ItemInserted(object sender, EventArgs e)
{
lbxLog.Items.Add(“Item inserted”);
}

void m_ListBox_ItemDeleted(object sender, EventArgs e)
{
lbxLog.Items.Add(“Item deleted”);
}

void m_ListBox_ItemAdded(object sender, EventArgs e)
{
lbxLog.Items.Add(“Item added”);
}
#endregion
}
}

運行後的結果如下,新增、插入、與刪除都能夠即時的偵測。

image

Link


  • How to detect if items are added to a ListBox (or CheckedListBox) control


  • LB_ADDSTRING message (Windows)


  • LB_DELETESTRING message (Windows)


  • LB_INSERTSTRING message (Windows)