2008-12-18 28 views
28

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.¿Cómo puedo agregar un menú contextual a ListBoxItem?

¿Alguien conoce una mejor manera?

+0

¿No puedes diseñar de otra manera? No puedo pensar en una IU como esta ... Nunca pensaría en hacer clic derecho en un elemento del cuadro de lista. – Gishu

+0

También estás en Winforms o WPF? Las respuestas pueden variar dependiendo de eso. – Gishu

Respuesta

4

De esta manera el menú pop-up al lado del ratón

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

No hay otra manera: el menú contextual no pertenece al elemento en el cuadro de lista sino al propio listbox. 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.

27

Solo para explicar 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 de la apertura. 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 sencillo, pero debe conseguir que va: Añadir un cuadro de lista a un formulario y agregue 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())); 
    } "); 

la esperanza de que ayude. -Mike

+0

¡Muy útil! ¡Muchas gracias! – asmo

+0

Aparece un error que listboxContextMenu_Opening no existe en el contexto actual. –

1

si es sólo una cuestión de cómo activar o desactivar elementos de menú contextual, que podría ser más eficiente a sólo lo hacen cuando el menú contextual se puso en marcha en lugar de cada vez que cambia el cuadro de lista de selección:

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

En XAML se muestra así:

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

éste 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; 
    } 
} 
0
//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; 
    } 
} 
4

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; 

     } 
    } 
0

me gusta esto, esto funciona genial y rápido para mi

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

En una línea de código (más por la unión):

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