I have a ListBox and I want to add a context menu to each item in the list. I've seen the "solution" to have the right click select an item and suppress the context menu if on white space, but this solution feels dirty.
我有一个ListBox,我想为列表中的每个项目添加一个上下文菜单。我已经看到“解决方案”右键单击选择一个项目并禁止上下文菜单,如果在空白区域,但这个解决方案感觉很脏。
Does anyone know a better way?
有谁知道更好的方法?
This way the menu will pop up next to the mouse
这样,菜单将弹出鼠标旁边
private string _selectedMenuItem;
private readonly ContextMenuStrip collectionRoundMenuStrip;
public Form1()
{
var toolStripMenuItem1 = new ToolStripMenuItem {Text = "Copy CR Name"};
toolStripMenuItem1.Click += toolStripMenuItem1_Click;
var toolStripMenuItem2 = new ToolStripMenuItem {Text = "Get information on CR"};
toolStripMenuItem2.Click += toolStripMenuItem2_Click;
collectionRoundMenuStrip = new ContextMenuStrip();
collectionRoundMenuStrip.Items.AddRange(new ToolStripItem[] {toolStripMenuItem1, toolStripMenuItem2 });
listBoxCollectionRounds.MouseDown += listBoxCollectionRounds_MouseDown;
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
var info = GetInfoByName(_selectedMenuItem);
MessageBox.Show(info.Name + Environment.NewLine + info.Date);
}
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
Clipboard.SetText(_selectedMenuItem);
}
private void myListBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Right) return;
var index = myListBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
_selectedMenuItem = listBoxCollectionRounds.Items[index].ToString();
collectionRoundMenuStrip.Show(Cursor.Position);
collectionRoundMenuStrip.Visible = true;
}
else
{
collectionRoundMenuStrip.Visible = false;
}
}
Just to elaborate a little further to what Frans has said...Even though the ListBox owns the ContextMenuStrip, you can still customize the items in the menu strip at the time it's opening. Thus customizing it's contents based on the mouse position within the listbox.
The example below selects the item in the listbox based on a right mouse click and then customizes a context menu strip based on the item the user right-clicked on. This is a simple example but should get you going: Add a listbox to a form and add this code:
只是详细说明Frans所说的内容......即使ListBox拥有ContextMenuStrip,您仍然可以在菜单条打开时自定义菜单条中的项目。因此,根据列表框中的鼠标位置自定义其内容。下面的示例基于鼠标右键单击选择列表框中的项目,然后根据用户右键单击的项目自定义上下文菜单条。这是一个简单的示例,但应该让您:将列表框添加到表单并添加以下代码:
print(" #region Private Members
private ContextMenuStrip listboxContextMenu;
#endregion
private void Form1_Load( object sender, EventArgs e )
{
//assign a contextmenustrip
listboxContextMenu = new ContextMenuStrip();
listboxContextMenu.Opening +=new CancelEventHandler(listboxContextMenu_Opening);
listBox1.ContextMenuStrip = listboxContextMenu;
//load a listbox
for ( int i = 0; i < 100; i++ )
{
listBox1.Items.Add( "Item: " + i );
}
}
private void listBox1_MouseDown( object sender, MouseEventArgs e )
{
if ( e.Button == MouseButtons.Right )
{
//select the item under the mouse pointer
listBox1.SelectedIndex = listBox1.IndexFromPoint( e.Location );
if ( listBox1.SelectedIndex != -1)
{
listboxContextMenu.Show();
}
}
}
private void listboxContextMenu_Opening( object sender, CancelEventArgs e )
{
//clear the menu and add custom items
listboxContextMenu.Items.Clear();
listboxContextMenu.Items.Add( string.Format( "Edit - {0}", listBox1.SelectedItem.ToString() ) );
} ");
Hope that help. -Mike
希望有所帮助。 -麦克风
There's no other way: the context menu isn't owned by the item in the listbox but by the listbox itself. It's similar to the treeview control which also owns the context menu instead of the treenode. So whenever an item in the listbox is selected, set the context menu of the listbox according to the selected item.
没有其他方法:上下文菜单不归列表框中的项目所有,而是由列表框本身拥有。它类似于treeview控件,它也拥有上下文菜单而不是treenode。因此,每当选择列表框中的项目时,请根据所选项目设置列表框的上下文菜单。
And Here it is My Solution :
这是我的解决方案:
listBox_Usernames.ContextMenuStrip = contextMenuStripRemove;
listBox_Usernames.MouseUp += new MouseEventHandler(listBox_Usernames_MouseUp);
void listBox_Usernames_MouseUp(object sender, MouseEventArgs e)
{
int index = listBox_Usernames.IndexFromPoint(e.Location);
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
if (index != ListBox.NoMatches)
{
if (listBox_Usernames.SelectedIndex == index)
{
listBox_Usernames.ContextMenuStrip.Visible = true;
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
else
{
listBox_Usernames.ContextMenuStrip.Visible = false;
}
}
In XAML it shows like this:
在XAML中它显示如下:
<ListBox> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="Add User..."/> <MenuItem Header="Edit..."/> <MenuItem Header="Disable"/> </ContextMenu> </ListBox.ContextMenu> </ListBox>
If its just a question of enabling or disabling context menu items, it might be more efficient to only do it when the context menu is launched rather than every time the list box selection changes:
如果它只是启用或禁用上下文菜单项的问题,则仅在启动上下文菜单时而不是每次列表框选择更改时执行此操作可能更有效:
myListBox.ContextMenu.Popup += new EventHandler(myContextPopupHandler);
private void myContextPopupHandler(Object sender, System.EventArgs e)
{
if (SelectedItem != null)
{
ContextMenu.MenuItems[1].Enabled = true;
ContextMenu.MenuItems[2].Enabled = true;
}
else
{
ContextMenu.MenuItems[1].Enabled = false;
ContextMenu.MenuItems[2].Enabled = false;
}
}
this one is best...
这个最好......
using System.Windows.Forms;
ContextMenuStrip menu;
this.menu.Items.AddRange(new ToolStripItem[] { this.menuItem });
this.listBox.MouseUp += new MouseEventHandler(this.mouse_RightClick);
private void mouse_RightClick(object sender, MouseEventArgs e)
{
int index = this.listBox.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
menu.Visible = true;
}
else
{
menu.Visible = false;
}
}
//Create and Initialize the contextMenuStrip component
contextMenuStrip_ListaAulas = new ContextMenuStrip();
//Adding an Item
contextMenuStrip_ListaAulas.Items.Add("Modificar");
//Binding the contextMenuStrip with the ListBox
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
//The solution below
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
//select the item under the mouse pointer
listBox_Aulas.SelectedIndex = listBox_Aulas.IndexFromPoint(e.Location);
//if the selected index is an item, binding the context MenuStrip with the listBox
if (listBox_Aulas.SelectedIndex != -1)
{
listBox_Aulas.ContextMenuStrip = contextMenuStrip_ListaAulas;
}
//else, untie the contextMenuStrip to the listBox
else
{
listBox_Aulas.ContextMenuStrip = null;
}
}
I do like this, this works great and fast for me.
我喜欢这个,这对我来说很有效。
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if (Listbox.SelectedItem == null)
e.Cancel = true;
}
In one line of code (more for binding):
在一行代码中(更多用于绑定):
var datasource = new BindingList<string>( new List<string>( new string[] { "item1" } ) );
listbox.DataSource = datasource ;
listbox.ContextMenu = new ContextMenu(
new MenuItem[] {
new MenuItem("Delete",
new EventHandler( (s,ev) =>
datasource.Remove(listbox.SelectedItem.ToString())
)
)
});
private void buttonAdd_Click(object sender, EventArgs e)
{
datasource.Add( textBox.Text );
}
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2008/12/18/5147d1566e2aaf9f26c0a386e134be56.html。