我在WinForms应用程序中使用了ListView
,该应用程序包含许多值以及一些组。组标题仅显示组的名称,因此我想在组标题中添加一个上下文菜单,其中包含“显示描述”项以显示该组的长摘要。
在谷歌搜索一段时间后,我只找到了具有此功能的第三方控件。
如何在不使用第三方软件的情况下将ContextMenu
添加到群组标头?
答案 0 :(得分:3)
您可以向services
发送LVM_HITTEST
条消息。当您将ListView
传递给-1
时,如果返回值大于wParam
并且在结果中设置了-1
,则LVHT_EX_GROUP_HEADER
方法的返回值将点击组索引。
<强>实施强>
在下面的实现中,我已将SendMessage
事件添加到GroupHeaderClick
类。您可以通过这种方式简单地处理事件:
MyListView
以下是private void myListView1_GroupHeaderClick(object sender, int e)
{
//Show ContextMenuStrip here. Or just for example:
MessageBox.Show(myListView1.Groups[e].Header);
}
实施:
MyListView
答案 1 :(得分:1)
只有将组添加到项目之前,Reza Aghaei的解决方案才有效。如果在已经添加项目之后添加了一个组,则该组将失败,因为SendMessage函数返回错误的索引。它实际上返回ID而不是索引。这是ListView组件中的一个已知问题。想法是将返回的值与组ID进行比较。
public class WListView : ListView
{
#region [ PInvoke ]
private const int LVM_HITTEST = 0x1000 + 18;
private const int LVM_SUBITEMHITTEST = 0x1000 + 57;
private const int LVHT_EX_GROUP_HEADER = 0x10000000;
[StructLayout(LayoutKind.Sequential)]
private struct LVHITTESTINFO
{
public int pt_x;
public int pt_y;
public int flags;
public int iItem;
public int iSubItem;
public int iGroup;
}
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref LVHITTESTINFO ht);
#endregion
/// <summary>
/// Occurs when a group is clicked.
/// </summary>
[Category("Behavior")]
[Description("Occurs when a group header is clicked.")]
public event EventHandler<ListViewGroupClickEventArgs> GroupClick;
/// <summary>
/// Raises the GroupClick event.
/// </summary>
/// <param name="e">Event arguments.</param>
protected virtual void OnGroupHeaderClick(ListViewGroupClickEventArgs e)
{
GroupClick?.Invoke(this, e);
}
/// <summary>
/// Raises the Control.MouseDoubleClick event.
/// </summary>
/// <param name="e">Event arguments.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
var group = TestGroupHit(e);
if (group == null)
{
return;
}
switch (e.Clicks)
{
case 1:
OnGroupHeaderClick(new ListViewGroupClickEventArgs(group));
break;
}
}
private ListViewGroup TestGroupHit(MouseEventArgs e)
{
var ht = new LVHITTESTINFO { pt_x = e.X, pt_y = e.Y };
var msg = View == System.Windows.Forms.View.Details ? LVM_SUBITEMHITTEST : LVM_HITTEST;
var value = SendMessage(Handle, msg, -1, ref ht);
if (value != -1 && (ht.flags & LVHT_EX_GROUP_HEADER) != 0)
{
return FindGroupByID(value);
}
return null;
}
private ListViewGroup FindGroupByID(int id)
{
foreach (ListViewGroup group in Groups)
{
if (group.ExtractID() == id)
{
return group;
}
}
return null;
}
}
属性Group.ID是非公共的。这是提取它的扩展名。
public static int ExtractID(this ListViewGroup group)
{
try
{
return (int) group
.GetType()
.GetProperty("ID", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(group, new object[0]);
}
catch
{
return -1;
}
}
请注意,根据具体情况,反射可能会很耗时。