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.
13 réponses
string name = "the_name_you_know";
Control ctn = this.Controls[name];
ctn.Text = "Example...";
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.
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.
ç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));
}
}
}
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>"];
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;
}
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;
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];
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! :)
Jetez un oeil à la ToolStrip.Collection d'articles. Il a même une méthode de recherche disponible.
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; }
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);