c# winforms listbox contextmenu

c# - ¿Cómo puedo agregar un menú contextual a ListBoxItem?



winforms contextmenu (10)

Tengo un ListBox y quiero agregar un menú contextual a cada elemento en la lista. He visto la "solución" para hacer clic con el botón derecho, seleccionar un elemento y suprimir el menú contextual si está en blanco, pero esta solución parece sucia.

¿Alguien sabe una mejor manera?


No hay otra manera: el menú contextual no es propiedad del elemento en el cuadro de lista, sino del propio cuadro de lista. Es similar al control treeview que también posee el menú contextual en lugar del treenode. Por lo tanto, cada vez que se selecciona un elemento en el cuadro de lista, configure el menú contextual del cuadro de lista de acuerdo con el elemento seleccionado.


Solo para elaborar un poco más de lo que Frans ha dicho ... Aunque el ListBox posee el ContextMenuStrip, aún puede personalizar los elementos en la tira de menú en el momento en que se abre. Por lo tanto, la personalización de sus contenidos se basa en la posición del mouse dentro del cuadro de lista.
El siguiente ejemplo selecciona el elemento en el cuadro de lista basado en un clic con el botón derecho del mouse y luego personaliza una tira de menú contextual según el elemento en el que el usuario hizo clic derecho. Este es un ejemplo simple, pero debería ayudarte: agrega un cuadro de lista a un formulario y agrega este código:

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() ) ); } ");

Espero que ayudes. -Micro


Si solo se trata de habilitar o deshabilitar elementos del menú contextual, podría ser más eficiente hacerlo solo cuando se inicia el menú contextual en lugar de cada vez que cambia la selección del cuadro de lista:

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; } }


//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; } }


Y aquí está mi solución:

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; } }


este es el mejor ...

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; } }


En XAML se muestra así:

<ListBox> <ListBox.ContextMenu> <ContextMenu> <MenuItem Header="Add User..."/> <MenuItem Header="Edit..."/> <MenuItem Header="Disable"/> </ContextMenu> </ListBox.ContextMenu> </ListBox>


De esta manera, el menú aparecerá al lado del 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; } }


Me gusta esto, esto funciona genial y rápido para mí.

private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { if (Listbox.SelectedItem == null) e.Cancel = true; }


En una línea de código (más para vincular):

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 ); }