web-dev-qa-db-fra.com

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

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

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

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

Ceci est dû au fait que je génère dynamiquement ToolStripMenuItems à partir d’un fichier XML et que j’ai besoin de référencer les menuitems par leurs noms générés dynamiquement.

57
user186249

Utilisez la méthode Control.ControlCollection.Find .

Essaye ça:

this.Controls.Find()
109
Adriaan Stander
string name = "the_name_you_know";

Control ctn = this.Controls[name];

ctn.Text = "Example...";
35
vaNIts
Control GetControlByName(string Name)
{
    foreach(Control c in this.Controls)
        if(c.Name == Name)
            return c;

    return null;
}

Ne pas en tenir compte, je réinvente les roues.

9
anonymous coward

En supposant que vous ayez l'objet menuStrip et que le menu ne comporte qu'un seul niveau, 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 dans 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é.

Pour éviter les exceptions, vous pouvez utiliser FirstOrDefault au lieu de SingleOrDefault/Single, ou simplement renvoyer une séquence si vous pouviez avoir des doublons Name.

6
dmihailescu

this.Controls.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
o3o

En supposant que vous ayez Windows.Form Form1 en tant que formulaire parent qui possède le menu que vous avez créé. Un des attributs du formulaire est nommé .Menu. Si le menu a été créé par programme, il devrait être identique, il serait 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 la balise Open et portait le nom 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;
3
shooky56
this.Controls["name"];

C'est le code réel 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;
    }
}

contre:

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
Philip Wallace

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

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

3
V1NNY

L'un des meilleurs moyens consiste à utiliser une seule ligne de code comme celle-ci:

Dans cet exemple, nous recherchons tous PictureBox par leur nom dans un formulaire.

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

Le plus important est le deuxième paramètre 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
daniele3004

Puisque vous les générez de manière dynamique, conservez un mappage 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

Regardez la collection ToolStrip.Items. Il a même une méthode de recherche disponible.

0
Neil

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

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

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

child.MouseDown += new MouseEventHandler(dragDown);
0
carefulnow1

Vous pouvez faire ce qui suit:

 private ToolStripMenuItem getToolStripMenuItemByName (string nameParam) 
 {
 poureach (Contrôle ctn dans ces contrôles) 
 
 if (ctn est ToolStripMenuItem) 
 {
 if (ctn.Nom = nameParam) 
 {
 renvoyer ctn; 
} 
} 
} 
 retourne null; 
} 
0
Koekiebox

Vous pouvez utiliser la fonction de recherche dans votre classe de formulaire. Si vous voulez transtyper (Label), (TextView) ... etc., vous pourrez ainsi utiliser des fonctionnalités spéciales d'objets. Ce sera l'objet retour Label.

(Label)this.Controls.Find(name,true)[0];

name: nom de l'élément recherché dans le formulaire

true: Rechercher dans toutes les valeurs booléennes de Children

0
Ferhat KOÇER