Location of Context Menu in Listview

O

O.B.

Assume a context menu is associated with a listview. Upon opening the
context menu, is there a way to determine which row in the listview
that the context menu was invoked upon?
 
L

Lasse Vågsæther Karlsen

O.B. said:
Assume a context menu is associated with a listview. Upon opening the
context menu, is there a way to determine which row in the listview
that the context menu was invoked upon?

I think you can override the MouseDown event to handle that before the
menu pops up.
 
J

Joe Cool

Assume a context menu is associated with a listview. Upon opening the
context menu, is there a way to determine which row in the listview
that the context menu was invoked upon?

By default, the item that was selected. If none is selected, and you
right click in an area where there are no items, it appears with the
upper left corner aligned with the mouse.
 
O

O.B.

Joe said:
By default, the item that was selected. If none is selected, and you
right click in an area where there are no items, it appears with the
upper left corner aligned with the mouse.

That wasn't too helpful.
 
O

O.B.

Lasse said:
I think you can override the MouseDown event to handle that before the
menu pops up.

I can override the MouseDown within the ListView and check to see if it
is a right-click, but then what? Is there a quick way to determine
which item was right-clicked?
 
V

vvnraman

Assume a context menu is associated with a listview. Upon opening the
context menu, is there a way to determine which row in the listview
that the context menu was invoked upon?

Yes...
There are two ways in which you can achieve this.
First you'll have to handle the MouseDown event of the ListView
control.
Suppose you have these three options in the context menu
Copy
Paste
Delete

The event handlers for these will not be called when the user right
clicks on the ListView and the context menu appears but the MouseDown
event will fire on a right click.

Now you can use the method GetChildAt(int x, int y)
or
HitTest(int x, int y)
to find out the exact listViewItem.
HitTest is a better method to use as it will give you the subitem if
any, when the sub item was clicked.

The only drawback of these is that if the user right clicks on a
ListViewItem but not on the text which is displayed there then it
doesn't works.

I wrote a small program and its working fine.
I'll copy paste the code here.
Add a ListView and a ContextMenuStrip to your form.
Add Copy, Paste, Cut, Delete as the four menu items.
Set the FullRowSelected of the ListView to true. (Necessary)
Set the GridLines to true.
Set the View to Details.

Here's the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace ContextMenuListViewItem
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeUserComponent();
}
private void InitializeUserComponent()
{
ListViewItem listViewItem1 = new
System.Windows.Forms.ListViewItem(new string[] {
"file1.txt",
"Documents",
"29 Kb",
"Text File"}, -1);
ListViewItem listViewItem2 = new
System.Windows.Forms.ListViewItem(new string[] {
"mypic.jpeg",
"My Pictures",
"387 Kb",
"JPEG File"}, -1);
ListViewItem listViewItem3 = new
System.Windows.Forms.ListViewItem(new string[] {
"Terminator III.avi",
"My Movies",
"700 Mb",
"AVI File"}, -1);
ListViewItem listViewItem4 = new
System.Windows.Forms.ListViewItem(new string[] {
"Help.chm",
"My eBooks",
"12 Mb",
"CHM File"}, -1);

ColumnHeader columnHeader1 = new
System.Windows.Forms.ColumnHeader();
columnHeader1.Text = "File Name";
columnHeader1.Width = 111;
ColumnHeader columnHeader2 = new
System.Windows.Forms.ColumnHeader();
columnHeader2.Text = "Folder";
columnHeader2.Width = 126;
ColumnHeader columnHeader3 = new
System.Windows.Forms.ColumnHeader();
columnHeader3.Text = "Size";
ColumnHeader columnHeader4 = new
System.Windows.Forms.ColumnHeader();
columnHeader4.Text = "Type";
columnHeader4.Width = 108;

this.listView1.Columns.AddRange(new
System.Windows.Forms.ColumnHeader[] {
columnHeader1,
columnHeader2,
columnHeader3,
columnHeader4});

this.listView1.ContextMenuStrip = this.contextMenuStrip1;

this.listView1.Items.AddRange(new
System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3,
listViewItem4});

}
private ListViewItem lvItem = null;

private void contextMenuStrip1_Opening(object sender,
CancelEventArgs e)
{
// If its a right click
if(!MousePosition.IsEmpty)
{
Point p = PointToClient(new Point(MousePosition.X,
MousePosition.Y));

// Using HitTest
/*//
ListViewHitTestInfo lvhtInfo =
this.listView1.HitTest(p);
if (lvhtInfo != null)
{
lvItem = lvhtInfo.Item;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}\r\n", p.ToString());
sb.AppendFormat("{0}\r\n", lvhtInfo.ToString());
if (lvhtInfo.Item != null)
{
sb.AppendFormat("{0}\r\n",
lvhtInfo.Item.ToString());
}
if (lvhtInfo.SubItem != null)
{
sb.AppendFormat("{0}\r\n",
lvhtInfo.SubItem.ToString());
}
textBox1.Text = sb.ToString();
}
//*/
// Using GetItemAt
//*//
ListViewItem currLvItem =
this.listView1.GetItemAt(p.X, p.Y);
if (currLvItem != null)
{
lvItem = currLvItem;
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}\r\n", p.ToString());
sb.AppendFormat("{0}\r\n", currLvItem.ToString());
sb.AppendFormat("{0}\r\n", currLvItem.Text);
if (currLvItem.SubItems != null)
{
foreach (ListViewItem.ListViewSubItem
lvSubItem in currLvItem.SubItems)
{
sb.AppendFormat("{0}\r\n",
lvSubItem.Text);
}
}
textBox1.Text = sb.ToString();
}
//*/
}
contextMenuStrip1.Items.Clear();
ToolStripMenuItem tsmItem = null;
if (lvItem != null)
{
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Copy " + lvItem.Text;
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Paste";
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Cut " + lvItem.Text;
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Delete " + lvItem.Text;
contextMenuStrip1.Items.Add(tsmItem);
}
else
{
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Copy";
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Paste";
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Cut";
contextMenuStrip1.Items.Add(tsmItem);
tsmItem = new ToolStripMenuItem();
tsmItem.Text = "Delete";
contextMenuStrip1.Items.Add(tsmItem);
}
}
}
}

You'll notice that when you use GetItemAt(), the ListViewSubItem are
not taken into account.

Hope this helps
Prateek Raman
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top