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.
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 en tenir compte, je réinvente les roues.
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
.
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));
}
}
}
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;
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;
}
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! :)
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];
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>"];
Regardez la collection ToolStrip.Items. Il a même une méthode de recherche disponible.
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);
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; }
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