2009-10-08 31 views
44

Tengo un ToolStripMenuItem llamado "myMenu". ¿Cómo puedo acceder a este modo:Obtenga un control de Windows Forms por nombre en C#

/* Normally, I would do: */ 
this.myMenu... etc. 

/* But how do I access it like this: */ 
String name = myMenu; 
this.name... 

Esto se debe a que estoy generando dinámicamente ToolStripMenuItems desde un archivo XML y la necesidad de hacer referencia a los elementos del menú por sus nombres generados dinámicamente.

Respuesta

84

Utilice el método Control.ControlCollection.Find.

Prueba esto:

this.Controls.Find() 
+3

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection .find% 28VS.80% 29.aspx – RvdK

+1

Esto funcionó perfectamente gracias –

+1

Esto no funciona para mí. Creo que porque, como o3o ha señalado, un ToolStripMenuItem no es un Control. – Luca

8
Control GetControlByName(string Name) 
{ 
    foreach(Control c in this.Controls) 
     if(c.Name == Name) 
      return c; 

    return null; 
} 

caso omiso de esto, reinventar ruedas.

+0

Más una solución de propósito general que la de Julien. Aún así funciona bien. –

+0

Solución increíble, esto es lo que estaba buscando desde hace mucho tiempo. ¡Gracias! :) – Vikyboss

+2

General-purpose-ish es bueno! +1 –

3

Dado que los está generando dinámicamente, mantenga un mapa entre una cadena y el elemento de menú, que permitirá una recuperación rápida.

// in class scope 
private readonly Dictionary<string, ToolStripMenuItem> _menuItemsByName = new Dictionary<string, ToolStripMenuItem>(); 

// in your method creating items 
ToolStripMenuItem createdItem = ... 
_menuItemsByName.Add("<name here>", createdItem); 

// to access it 
ToolStripMenuItem menuItem = _menuItemsByName["<name here>"]; 
+1

¡AHORA HAY UNA IDEA! +1 (aunque solo funciona si el control ya está en el diccionario) –

0

Eche un vistazo a la colección ToolStrip.Items. Incluso tiene un método de búsqueda disponible.

0

Usted puede hacer lo siguiente:

 
private ToolStripMenuItem getToolStripMenuItemByName(string nameParam) 
    { 
     foreach (Control ctn in this.Controls) 
     { 
      if (ctn is ToolStripMenuItem) 
       { 
        if (ctn.Name = nameParam) 
         { 
         return ctn; 
         } 
       } 
     } 
     return null; 
    } 
28
string name = "the_name_you_know"; 

Control ctn = this.Controls[name]; 

ctn.Text = "Example..."; 
+0

el único problema con ToolStripMenuItem es que no es un Control y tu código no funcionará. ; ( – dmihailescu

+1

) En realidad, esta respuesta es más cercana a la pregunta para mí. – TechNyquist

3
this.Controls["name"]; 

Este es el código real que es RAN:

public virtual Control this[string key] 
{ 
    get 
    { 
     if (!string.IsNullOrEmpty(key)) 
     { 
      int index = this.IndexOfKey(key); 
      if (this.IsValidIndex(index)) 
      { 
       return this[index]; 
      } 
     } 
     return null; 
    } 
} 

vs:

public Control[] Find(string key, bool searchAllChildren) 
{ 
    if (string.IsNullOrEmpty(key)) 
    { 
     throw new ArgumentNullException("key", SR.GetString("FindKeyMayNotBeEmptyOrNull")); 
    } 
    ArrayList list = this.FindInternal(key, searchAllChildren, this, new ArrayList()); 
    Control[] array = new Control[list.Count]; 
    list.CopyTo(array, 0); 
    return array; 
} 

private ArrayList FindInternal(string key, bool searchAllChildren, Control.ControlCollection controlsToLookIn, ArrayList foundControls) 
{ 
    if ((controlsToLookIn == null) || (foundControls == null)) 
    { 
     return null; 
    } 
    try 
    { 
     for (int i = 0; i < controlsToLookIn.Count; i++) 
     { 
      if ((controlsToLookIn[i] != null) && WindowsFormsUtils.SafeCompareStrings(controlsToLookIn[i].Name, key, true)) 
      { 
       foundControls.Add(controlsToLookIn[i]); 
      } 
     } 
     if (!searchAllChildren) 
     { 
      return foundControls; 
     } 
     for (int j = 0; j < controlsToLookIn.Count; j++) 
     { 
      if (((controlsToLookIn[j] != null) && (controlsToLookIn[j].Controls != null)) && (controlsToLookIn[j].Controls.Count > 0)) 
      { 
       foundControls = this.FindInternal(key, searchAllChildren, controlsToLookIn[j].Controls, foundControls); 
      } 
     } 
    } 
    catch (Exception exception) 
    { 
     if (ClientUtils.IsSecurityOrCriticalException(exception)) 
     { 
      throw; 
     } 
    } 
    return foundControls; 
} 
4

this.Controls.Find (nombre, searchAllChildren) no encuentra ToolStripItem porque ToolStripItem no es un control

using SWF = System.Windows.Forms; 
    using NUF = NUnit.Framework; 
    namespace workshop.findControlTest { 
    [NUF.TestFixture] 
    public class FormTest { 
     [NUF.Test]public void Find_menu() { 
      // == prepare == 
      var fileTool = new SWF.ToolStripMenuItem(); 
      fileTool.Name = "fileTool"; 
      fileTool.Text = "File"; 

      var menuStrip = new SWF.MenuStrip(); 
      menuStrip.Items.Add(fileTool); 

      var form = new SWF.Form(); 
      form.Controls.Add(menuStrip); 

      // == execute == 
      var ctrl = form.Controls.Find("fileTool", true); 

      // == not found! == 
      NUF.Assert.That(ctrl.Length, NUF.Is.EqualTo(0)); 
     } 
    } 
    } 
5

Asumiendo que tiene el objeto menuStrip y el menú es sólo un nivel, utilice:

ToolStripMenuItem item = menuStrip.Items 
    .OfType<ToolStripMenuItem>() 
    .SelectMany(it => it.DropDownItems.OfType<ToolStripMenuItem>()) 
    .SingleOrDefault(n => n.Name == "MyMenu"); 

Para niveles de menú más profundos, agregue más operadores SelectMany en la instrucción.

si desea buscar todos los elementos de menú en la tira a continuación, utilizar

ToolStripMenuItem item = menuStrip.Items 
    .Find("MyMenu",true) 
    .OfType<ToolStripMenuItem>() 
    .Single(); 

Sin embargo, asegúrese de que cada menú tiene un nombre diferente para evitar excepción lanzada por duplicados clave.

Para evitar excepciones que podría utilizar en lugar de FirstOrDefaultSingleOrDefault/Single, o simplemente devolver una secuencia de si podría tener Name duplicados.

2

Suponiendo que tiene Windows.Form Form1 como el formulario principal que posee el menú que ha creado. Uno de los atributos del formulario se llama .Menu. Si el menú se creó mediante programación, debería ser el mismo, y se reconocería como un menú y se colocaría en el atributo de menú del formulario.

En este caso, tenía un menú principal llamado File. Un submenú, llamado MenuItem bajo File contenía la etiqueta Open y se llamaba menu_File_Open. Lo siguiente funcionó. Asumiendo que

// So you don't have to fully reference the objects. 
using System.Windows.Forms; 

// More stuff before the real code line, but irrelevant to this discussion. 

MenuItem my_menuItem = (MenuItem)Form1.Menu.MenuItems["menu_File_Open"]; 

// Now you can do what you like with my_menuItem; 
0

Una solución sencilla sería la de repetir la lista de Controls en un bucle foreach. Algo como esto:

foreach (Control child in Controls) 
{ 
    // Code that executes for each control. 
} 

Así que ahora usted tiene su iterador, child, que es de tipo Control. Ahora haz lo que quieras con eso, personalmente, me encontré con esto en un proyecto que hice hace un tiempo en el que se añade un evento para este control, así:

child.MouseDown += new MouseEventHandler(dragDown); 
1

Utilizando el mismo método de Philip Wallace, podemos hacer de esta manera:

public Control GetControlByName(Control ParentCntl, string NameToSearch) 
    { 
     if (ParentCntl.Name == NameToSearch) 
      return ParentCntl; 

     foreach (Control ChildCntl in ParentCntl.Controls) 
     { 
      Control ResultCntl = GetControlByName(ChildCntl, NameToSearch); 
      if (ResultCntl != null) 
       return ResultCntl; 
     } 
     return null; 
    } 

Ejemplo:

public void doSomething() 
    { 
      TextBox myTextBox = (TextBox) this.GetControlByName(this, "mytextboxname"); 
      myTextBox.Text = "Hello!"; 
    } 

espero que ayude! :)

0

Uno de la mejor manera es una sola fila de código como este:

En este ejemplo buscamos todos PictureBox por su nombre en una forma

PictureBox[] picSample = 
        (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true); 

Lo más importante es la segunda de paramenter find.

si está seguro de que existe el nombre del control se puede utilizar directamente:

PictureBox picSample = 
         (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0]; 
Cuestiones relacionadas