2009-10-08 6 views
44

J'ai un ToolStripMenuItem appelé "myMenu". Comment puis-je accéder à ce comme ceci:Obtenir un contrôle Windows Forms par nom dans C#

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

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

Ceci est parce que je suis générer dynamiquement ToolStripMenuItems à partir d'un fichier XML et pour référencer menuitems par leurs noms générés dynamiquement.

Répondre

84

Utilisez la méthode Control.ControlCollection.Find.

Essayez ceci:

this.Controls.Find() 
+3

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

+1

Cela a fonctionné parfaitement grâce –

+1

Cela ne fonctionne pas pour moi. Je pense que, comme l'a souligné o3o, un ToolStripMenuItem n'est pas un contrôle. – Luca

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

    return null; 
} 

Mépris, je réinvente les roues.

+0

Plus d'une solution à usage général que celle de Julien. Ça marche toujours bien. –

+0

Super solution, c'est ce que je cherchais depuis longtemps. Merci! :) – Vikyboss

+2

General-purpose-ish est bon! +1 –

3

Puisque vous les générez dynamiquement, gardez une carte entre une chaîne et l'élément de menu, qui permettra une récupération rapide.

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

Maintenant, il y a une idée! +1 (bien que cela ne fonctionne que si le contrôle est déjà dans le dictionnaire) –

0

Jetez un coup d'oeil à la collection ToolStrip.Items. Il a même une méthode de recherche disponible.

0

Vous pouvez effectuer les opérations suivantes:

 
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

Le seul problème avec ToolStripMenuItem est que ce n'est pas un contrôle et votre code ne fonctionnera pas. ; ( – dmihailescu

+1

En fait, cette réponse est plus proche de la question pour moi. – TechNyquist

3
this.Controls["name"]; 

C'est le code réel qui est 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 (nom, searchAllChildren) ne trouve pas ToolStripItem parce ToolStripItem est pas un contrôle

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

En supposant que vous avez l'objet menuStrip et le menu est qu'un seul niveau, utilisez:

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

Pour les niveaux de menu plus profond, ajoutez plusieurs opérateurs SelectMany dans l'instruction.

si vous souhaitez rechercher tous les éléments de menu dans la bande puis utilisez

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

Cependant, assurez-vous que chaque menu a un nom différent pour éviter les doublons exception lancée par clé.

Pour éviter des exceptions que vous pouvez utiliser FirstOrDefault au lieu de SingleOrDefault/Single, ou tout simplement retourner une séquence si vous pourriez avoir Name doublons.

2

En supposant que vous avez Windows.Form Form1 comme formulaire parent propriétaire du menu que vous avez créé. L'un des attributs de la forme est nommé .Menu. Si le menu a été créé par programme, il doit être le même, et il sera reconnu comme un menu et placé dans l'attribut Menu du formulaire.

Dans ce cas, j'avais un menu principal appelé File. Un sous-menu, appelé MenuItem sous File contenait l'étiquette Open et portait le numéro menu_File_Open. Ce qui suit a fonctionné. En supposant que vous

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

Une solution simple serait de parcourir la liste Controls dans une boucle foreach. Quelque chose comme ceci:

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

Alors maintenant, vous avez votre iterator, child, qui est de type Control. Maintenant, faites ce que vous avec cela, personnellement, je trouve cela dans un projet, je l'ai fait il y a un moment où il a ajouté un événement pour ce contrôle, comme ceci:

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

En utilisant la même approche de Philip Wallace, nous pouvons faire comme ceci:

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

Exemple:

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

Je l'espère aider! :)

0

L'un des meilleur moyen est une seule ligne de code comme ceci:

Dans cet exemple, nous recherchons tous PictureBox par son nom sous une forme

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

Le plus important est la deuxième paramenter de find.

si vous êtes certain que le nom de contrôle existe, vous pouvez l'utiliser directement:

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