Obtenir un contrôle Windows Forms par nom en C#

J'ai un ToolStripMenuItem appelé "myMenu". Comment puis-je accéder à ceci comme ceci:

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

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

C'est parce que je génère dynamiquement ToolStripMenuItems à partir d'un fichier XML et que je dois référencer menuitems par leurs noms générés dynamiquement.

49
demandé sur Peter Mortensen 2009-10-08 13:49:03

13 réponses

Utilisez le contrôle .ControlCollection.Trouver Méthode.

Essayez ceci:

this.Controls.Find()
90
répondu Adriaan Stander 2014-10-03 11:36:47
string name = "the_name_you_know";

Control ctn = this.Controls[name];

ctn.Text = "Example...";
30
répondu vaNIts 2012-05-22 19:48:25
Control GetControlByName(string Name)
{
    foreach(Control c in this.Controls)
        if(c.Name == Name)
            return c;

    return null;
}

Ne pas tenir compte de cela, je réinvente roues.

8
répondu anonymous coward 2009-10-08 09:53:42

En supposant que vous avez l'objet menuStrip et que le menu n'a qu'un niveau de profondeur, utilisez:

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

Pour des niveaux de menu plus profonds, ajoutez plus D'opérateurs SelectMany dans l'instruction.

Si vous souhaitez rechercher tous les éléments de menu de la bande, 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 exceptions générées par les doublons de clés.

Pour éviter les exceptions vous pouvez utiliser FirstOrDefault au lieu de SingleOrDefault / Single, ou juste de retour d'une séquence si vous pourriez avoir Name dupliquer.

5
répondu dmihailescu 2012-08-30 13:56:52

ça.Contrôle.Find (name, searchAllChildren) ne trouve pas ToolStripItem car ToolStripItem n'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)); 
        }
     }
  }
4
répondu o3o 2013-05-24 20:24:33

Puisque vous les générez dynamiquement, Gardez une carte entre une chaîne et l'élément de menu, ce 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>"];
3
répondu Julien Lebosquain 2009-10-08 09:53:54
this.Controls["name"];

C'est le code qui est exécuté:

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;
}
3
répondu Philip Wallace 2009-10-28 18:33:45

En supposant que vous avez Windows.Form Form1 comme formulaire parent qui possède le menu que vous avez créé. L'un des attributs du formulaire est nommé .Menu. Si le menu a été créé par programme, il devrait être le même, et il serait reconnu comme un menu et placé dans L'attribut de Menu du formulaire.

Dans ce cas, j'avais un menu principal appelé File. Un sous-menu, appelé MenuItem sous File contenait la balise Open et était nommé menu_File_Open. La suite travaillé. 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;
3
répondu shooky56 2014-02-22 19:46:54

L'Un des meilleurs moyens est une seule ligne de code comme ceci:

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

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

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

Si vous êtes certain que le nom du contrôle existe, Vous pouvez l'utiliser directement:

  PictureBox picSample = 
                        (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0];
3
répondu daniele3004 2017-11-29 08:06:55

En Utilisant la même approche de Philip Wallace, nous pouvons le 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!";
    }

J'espère que ça aidera! :)

2
répondu V1NNY 2017-05-23 12:34:27

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

0
répondu Neil 2009-10-08 09:56:53

Vous pouvez faire ce qui suit:

private ToolStripMenuItem getToolStripMenuItemByName(string nameParam)
   {
      foreach (Control ctn in this.Controls)
         {
            if (ctn is ToolStripMenuItem)
               {
                   if (ctn.Name = nameParam)
                      {
                         return ctn;
                      }
                }
         }
         return null;
    }
0
répondu Koekiebox 2013-05-24 20:34:06

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

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

Donc, maintenant vous avez votre itérateur child, qui est de type Control. Maintenant, faites ce que vous voulez avec cela, personnellement, j'ai trouvé cela dans un projet que j'ai fait il y a un moment dans lequel il a ajouté un événement pour ce contrôle, comme ceci:

child.MouseDown += new MouseEventHandler(dragDown);
0
répondu carefulnow1 2016-06-26 04:36:42