用于 ListView 列操作的上下文菜单






2.50/5 (17投票s)
2004年1月27日
4分钟阅读

130313

1103
本文实现了一个简单的 ListView 控件列标题的右键菜单。点击列后,用户可以设置列的对齐方式、编辑其名称、删除选定的列或向 ListView 控件添加新列。文章还解释了 ListView 内置的列重新排序选项。
入门
在 Visual Studio 中以设计模式打开演示项目的 Form1
。注意,一个 System.Windows.Forms.ContextMenu
已被拖放到 Form1
下方边缘的挂板上。点击它。注意,"Context Menu" 字样出现在 Form1
的顶部。点击它。现在比较您看到的内容与文章的截图。它们应该看起来相似。
要实现您自己的右键菜单,只需在 "type here"(此处输入)的空白处添加描述性名称即可。如果您希望菜单选项像演示中的列对齐选项那样向右扩展,请在右侧的 "type here" 空白处输入;如果您希望菜单选项像 Column Delete(删除列)和 Column Add(添加列)那样向下扩展,请在下方的 "type here" 空白处输入。现在,您只需编写用户点击其中一个选项时要执行的代码,并在适当的时候显示菜单即可。
要实现您自己的右键菜单,只需从窗体设计器工具箱中将一个右键菜单对象拖放到窗体挂板上,然后输入您想要显示的选项。在您的程序中调出菜单,并响应用户点击右键菜单选项时触发的事件。
何时以及如何调出 ListView 右键菜单
Windows 用户习惯于 Redmond 的程序员们(boys and girls of Redmond)告知,当他们想要更改某些内容时,就点击它。因此,自然地,点击列标题区域(Col 1 Col2 ...)应该会调出右键菜单。
此外,您必须知道用户点击了哪一列。幸运的是,每个 ListView
控件都有一个列点击事件。它响应在列标题区域的点击。它提供了一个被点击列的索引,我们可以从这个索引定义所选列的各种内容。下面是我冗长的列点击代码。别让它吓跑你,它其实很简单。
首先,列的零基索引(零是左边的列)从 ColumnClickEventArg e
中获取,并保存在 form1
对象的某个字段中。我们还局部保存当前列的文本对齐方式。
长长的 "if alignment ==
" 梯子是可选的。它所做的只是放置一个单选按钮检查,以显示所选列当前的文本对齐方式,当该子选项弹出到右侧时。
最后,我们显示(调出)右键菜单。这里的一个改进是获取 ListView
的客户区域,然后用它来确定 ContextMenu
的位置。现在,它显示在您光标附近的 50,50 位置。
private void listView1_ColumnClick(object sender,
System.Windows.Forms.ColumnClickEventArgs e)
{
// save the zero based index of the column
// you clicked on in a Class visible field
clickedColumnIndex = e.Column;
// Get the current column horizontal text alignment
HorizontalAlignment align =
listView1.Columns[clickedColumnIndex].TextAlign;
// on the context menu, reflect the current horizontal
// text alignment of the column you just
// clicked on in the Column Context menu
if(align == HorizontalAlignment.Center)
{
menuItem4ColAlignCenter.Checked = true;
menuItem4ColAlignCenter.RadioCheck = true;
menuItem3ColAlignLeft.RadioCheck = false;
menuItem3ColAlignLeft.Checked = false;
menuItem2ColAlignRight.RadioCheck = false;
menuItem2ColAlignRight.Checked = false;
}
else if(align == HorizontalAlignment.Left)
{
menuItem4ColAlignCenter.Checked = false;
menuItem4ColAlignCenter.RadioCheck = false;
menuItem3ColAlignLeft.Checked = true;
menuItem3ColAlignLeft.RadioCheck = true;
menuItem2ColAlignRight.RadioCheck = false;
menuItem2ColAlignRight.Checked = false;
}
else if(align == HorizontalAlignment.Right)
{
menuItem4ColAlignCenter.Checked = false;
menuItem4ColAlignCenter.RadioCheck = false;
menuItem3ColAlignLeft.Checked = false;
menuItem3ColAlignLeft.RadioCheck = false;
menuItem2ColAlignRight.Checked = true;
menuItem2ColAlignRight.RadioCheck = true;
}
// pop up the designer created context menu
contextMenu1.Show(listView1,new Point(50,50));
}
响应右键菜单的列添加
当用户点击 ContextMenu
的 "ColumnAdd"(添加列)时,会触发一个事件。下面是事件代码以及我的响应代码。首先,我调出一个安装在分组框上的小型对话框。在该对话框中,用户可以选择新列的文本对齐方式并输入新名称。
private void menuItem6ColAdd_Click(object sender,
System.EventArgs e) // Show Column Add groupBox dialog
{
groupBox1.Visible = true;
}
当用户点击 "Accept"(接受)(位于简单对话框的分组框上)时,将触发下面的事件。用户选择的所有列信息都会被计算,然后放入一个名为 hdr
的 ColumnHeader
对象中。最后,调用 ListView.Columns.Insert(at index)
,使用之前保存的被点击列的索引。这是 Accept 按钮的代码。
private void button1_Click(object sender, System.EventArgs e) // Accept button for Add new Col dialog { //Grab user input to set up new Column ColumnHeader hdr = new ColumnHeader(); if(radioButton1.Checked) //Set header alignment hdr.TextAlign = HorizontalAlignment.Left; // based on radio button checks else if(radioButton3.Checked) hdr.TextAlign = HorizontalAlignment.Right; else hdr.TextAlign = HorizontalAlignment.Center; hdr.Text = textBox1.Text; // header column text hdr.Width = textBox1.Text.Length * (int)listView1.Font.SizeInPoints + 10; // Approx width necessary // Insert the new column listView1.Columns.Insert(clickedColumnIndex, hdr); groupBox1.Visible = false; // hide the new column dialog }
所有其他的 ContextMenu
点击响应都类似,所以我在此不详述。
使用 ListView 控件的一些技巧
- 您新添加到窗体上的
ListView
控件,除非您首先点击ListView
,然后打开其属性对话框窗口并将 View(视图)更改为 Details(详细信息),否则不会与上面的截图相似。默认不是 Details,所以您需要立即执行此操作。我认为默认的ListView
控件是为图像或图标等设置的。它开箱即用时看起来不像上面的示例。 - 在
listView1
的属性对话框中有一个名为AllowColumnReorder
(允许列重排)的属性。默认值为false
。如果将其设置为true
,用户将能够点击然后拖动列,将其从最右侧移动到最左侧的第一个位置。在演示程序中,AllowColumnRecorder
已设置为true
,您可以尝试一下。 - 设置列宽存在某种算法。它一定类似于 "
listView1.Font
的磅值乘以标题文本长度"。我使用了hdr.Width = textBox1.Text.Length * (int)listView1.Font.SizeInPoints + 10;
,这似乎是合适的。 - 我徒劳地寻找一种方法来高亮显示用户点击的列的标题文本。除了关于所有者绘制/绘制构造的引用之外,我找不到任何方法,而这些我一直未能理解。肯定有一种简单的方法。高亮显示
ListView
控件中的一行很容易。只需listView.Item.BackColor = Color.whatever
。
我最初认为在 ListView
的列标题上实现右键菜单会很麻烦。结果证明我是错的。对我来说,代码相当直观。希望这个解释能有所帮助。
历史
首个版本发布于 2004 年 1 月。