2009-10-08 16 views
44

Ho un oggetto ToolStripMenuItem chiamato "myMenu". Come è possibile accedere a questo modo:Ottenere un controllo Windows Form per nome in C#

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

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

Questo è perché sto generando dinamicamente ToolStripMenuItems da un file XML e la necessità di fare riferimento menuitems con i loro nomi generati in modo dinamico.

risposta

84

utilizzare il metodo Control.ControlCollection.Find.

Prova questa:

this.Controls.Find() 
+3

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

+1

Questo ha funzionato perfettamente grazie –

+1

Questo non funziona per me. Penso perché, come ha sottolineato o3o, un ToolStripMenuItem non è un controllo. – Luca

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

    return null; 
} 

Ignorare questo, mi reinventare ruote.

+0

Più di una soluzione generica per tutti gli usi di Julien. Funziona ancora bene però. –

+0

Soluzione eccezionale, questo è quello che stavo cercando da molto tempo. Grazie! :) – Vikyboss

+2

General-purpose-ish è buono! +1 –

3

Dal momento che li stai generando dinamicamente, tieni una mappa tra una stringa e la voce di menu, che consentirà il recupero rapido.

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

Ora, c'è un'idea! +1 (anche se funziona solo se il controllo è già nel dizionario) –

0

Dai un'occhiata alla collezione ToolStrip.Items. Ha anche un metodo di ricerca disponibile.

0

È possibile effettuare le seguenti:

 
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

l'unico problema con ToolStripMenuItem è che non è un controllo e il tuo codice non funzionerà. ( – dmihailescu

+1

In realtà questa risposta è più vicina alla domanda per me. – TechNyquist

3
this.Controls["name"]; 

Questo è il codice effettivo che è 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 (nome, searchAllChildren) non trova ToolStripItem perché ToolStripItem non è un controllo

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

Supponendo di avere l'oggetto menuStrip e il menu è solo un livello profondo, uso:

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

Per livelli di menu più profondi aggiungere più operatori SelectMany nell'istruzione.

se si desidera cercare tutte le voci di menu nella striscia quindi utilizzare

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

Tuttavia, assicurarsi che ogni menù ha un nome diverso per evitare eccezione generata dai duplicati delle chiavi.

Per evitare eccezioni si potrebbe usare FirstOrDefault invece di SingleOrDefault/Single, o semplicemente restituire una sequenza se si potrebbe avere Name duplicati.

2

Supponendo di avere Windows.Form Form1 come modulo principale che possiede il menu che hai creato. Uno degli attributi del modulo è denominato .Menu. Se il menu è stato creato a livello di programmazione, dovrebbe essere lo stesso e verrà riconosciuto come menu e inserito nell'attributo Menu del modulo.

In questo caso, ho avuto un menu principale chiamato File. Un sottomenu, chiamato MenuItem sotto File conteneva il tag Open ed era denominato menu_File_Open. Il seguente ha funzionato. Supponendo che si

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

Una soluzione semplice sarebbe quella di scorrere l'elenco Controls in un ciclo foreach. Qualcosa di simile a questo:

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

Così ora avete il vostro iteratore, child, che è di tipo Control. Ora faccio quello che sarà con questo, personalmente ho trovato questo in un progetto che ho realizzato qualche tempo fa in cui ha aggiunto un evento per questo controllo, in questo modo:

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

Utilizzando lo stesso approccio di Philip Wallace, possiamo fare in questo modo:

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

Esempio:

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

spero che aiuta! :)

0

Uno dei modi migliori è una singola riga di codice come questo:

In questo esempio abbiamo Cerca tutti i PictureBox per nome in una forma

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

cosa più importante è il secondo paramenter di find.

se si è certi che il nome esiste controllo È possibile utilizzare direttamente esso:

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