2009-10-08 10 views
44

Mam ToolStripMenuItem nazwie "myMenu". Jak mogę uzyskać dostęp do tego tak:Pobierz formant Windows Forms według nazwy w C#

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

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

To dlatego, że jestem dynamicznie generując ToolStripMenuItems z pliku XML i trzeba odwołać elementów menu przez ich nazw generowanych dynamicznie.

Odpowiedz

84

Użyj metody Control.ControlCollection.Find.

Spróbuj tego:

this.Controls.Find() 
+3

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

+1

To działało idealnie dzięki –

+1

To nie działa dla mnie. Myślę, że ponieważ, jak o3o wskazał, ToolStripMenuItem nie jest Kontrolą. – Luca

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

    return null; 
} 

Lekceważenie tego, że nowo koła.

+0

Więcej rozwiązania ogólnego przeznaczenia niż Julien's. Nadal działa dobrze. –

+0

Niesamowite rozwiązanie, tego właśnie szukałem przez długi czas. Dzięki! :) – Vikyboss

+2

Ogólny cel jest dobry! +1 –

3

Ponieważ generujesz je dynamicznie, zachowaj mapę pomiędzy ciągiem a elementem menu, który umożliwi szybkie pobieranie.

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

Teraz jest pomysł! +1 (chociaż działa tylko wtedy, gdy formant jest już w słowniku) –

0

Zobacz kolekcję ToolStrip.Items. Ma nawet dostępną metodę wyszukiwania.

0

można wykonać następujące czynności:

 
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

Jedynym problemem związanym z ToolStripMenuItem jest to, że nie jest to Kontrola, a twój kod nie będzie działał. ; ( – dmihailescu

+1

Właściwie ta odpowiedź jest mi bliższa. – TechNyquist

3
this.Controls["name"]; 

Jest to rzeczywisty kod, który jest prowadzony:

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 (nazwa, searchAllChildren) nie znajdzie ToolStripItem ponieważ ToolStripItem nie jest kontrola

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

Zakładając, że obiekt menuStrip i menu jest tylko jeden poziom głęboko, przeznaczenie:

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

Aby uzyskać głębsze poziomy menu, dodaj więcej operatorów SelectMany do wyciągu.

jeśli chcesz wyszukać wszystkie pozycje menu w pasku następnie użyć

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

Jednak upewnić się, każdy menu ma inną nazwę, aby uniknąć wyjątek rzucony przez kluczowych duplikatów.

Aby uniknąć wyjątków można użyć FirstOrDefault zamiast SingleOrDefault/Single, lub po prostu wrócić sekwencję, czy może masz Name duplikatów.

2

Zakładając, że masz Windows.Form Form1 jako formę nadrzędną, do której należy utworzone menu. Jeden z atrybutów formularza nosi nazwę .Menu. Jeśli menu zostało utworzone programowo, powinno być takie samo, i zostanie rozpoznane jako menu i umieszczone w atrybucie Menu formularza.

W tym przypadku miałem menu główne o nazwie File. Podmenu o nazwie MenuItem pod File zawierało tag Open i nosiło nazwę menu_File_Open. Następujące pracował. Zakładając, że

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

Prostym rozwiązaniem byłoby iterację listy Controls w foreach pętli. Coś takiego:

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

Więc teraz masz iterator, child, który jest typu Control. Teraz to, co będzie z tym, osobiście uważam, że ten w projekcie zrobiłem jakiś czas temu, w którym dodaje zdarzenie do tej kontroli, tak:

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

Używając tego samego podejścia Philip Wallace możemy zrobić tak:

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

Przykład:

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

mam nadzieję, że to pomoże! :)

0

Jednym z najlepszych sposobów jest pojedynczy wiersz kodu tak:

W tym przykładzie szukamy wszystkie PictureBox nazwy w formie

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

najważniejsza jest druga paramenter od find.

jeśli jesteś pewien, że nazwa kontrola istnieje można bezpośrednio wykorzystać go:

PictureBox picSample = 
         (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0]; 
Powiązane problemy