65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.50/5 (17投票s)

2004年1月27日

4分钟阅读

viewsIcon

130313

downloadIcon

1103

本文实现了一个简单的 ListView 控件列标题的右键菜单。点击列后,用户可以设置列的对齐方式、编辑其名称、删除选定的列或向 ListView 控件添加新列。文章还解释了 ListView 内置的列重新排序选项。

ListView Context Menu Demo

入门

在 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"(接受)(位于简单对话框的分组框上)时,将触发下面的事件。用户选择的所有列信息都会被计算,然后放入一个名为 hdrColumnHeader 对象中。最后,调用 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 控件的一些技巧

  1. 您新添加到窗体上的 ListView 控件,除非您首先点击 ListView,然后打开其属性对话框窗口并将 View(视图)更改为 Details(详细信息),否则不会与上面的截图相似。默认不是 Details,所以您需要立即执行此操作。我认为默认的 ListView 控件是为图像或图标等设置的。它开箱即用时看起来不像上面的示例。
  2. listView1 的属性对话框中有一个名为 AllowColumnReorder(允许列重排)的属性。默认值为 false。如果将其设置为 true,用户将能够点击然后拖动列,将其从最右侧移动到最左侧的第一个位置。在演示程序中,AllowColumnRecorder 已设置为 true,您可以尝试一下。
  3. 设置列宽存在某种算法。它一定类似于 "listView1.Font 的磅值乘以标题文本长度"。我使用了 hdr.Width = textBox1.Text.Length * (int)listView1.Font.SizeInPoints + 10;,这似乎是合适的。
  4. 我徒劳地寻找一种方法来高亮显示用户点击的列的标题文本。除了关于所有者绘制/绘制构造的引用之外,我找不到任何方法,而这些我一直未能理解。肯定有一种简单的方法。高亮显示 ListView 控件中的一行很容易。只需 listView.Item.BackColor = Color.whatever

我最初认为在 ListView 的列标题上实现右键菜单会很麻烦。结果证明我是错的。对我来说,代码相当直观。希望这个解释能有所帮助。

历史

首个版本发布于 2004 年 1 月。

© . All rights reserved.