Get a Windows Forms control by name in C#

This is because I am dynamically generating ToolStripMenuItems from an XML file and need to reference MenuItems by their dynamically generated names.

asked Oct 8, 2009 at 9:49 user186249 user186249

14 Answers 14

this.Controls.Find() 
31.6k 22 22 gold badges 109 109 silver badges 132 132 bronze badges answered Oct 8, 2009 at 9:53 Adriaan Stander Adriaan Stander 166k 31 31 gold badges 292 292 silver badges 286 286 bronze badges Commented Oct 8, 2009 at 9:55

This doesn't work for me. I think because, as o3o has pointed out, a ToolStripMenuItem is not a Control.

Commented Nov 28, 2010 at 17:27

For a textbox, I had to cast to the control type and take the first element like this: ((TextBox) frm.Controls.Find("controlName",true)[0]).Text = "yay";

Commented Apr 16, 2012 at 1:05 @DanW this is so much like Java Commented Dec 18, 2017 at 9:04

Thanks @mrid! This is what worked for me when I'm using one function for all textboxes in powershell. I hope this helps anyone else. ([TextBox]$MainForm.Controls.Find($this.Name,$true)[0]).SelectAll()

Commented Nov 9, 2023 at 21:11
string name = "the_name_you_know"; Control ctn = this.Controls[name]; ctn.Text = "Example. "; 
12.7k 16 16 gold badges 80 80 silver badges 111 111 bronze badges answered Oct 28, 2009 at 18:18 529 3 3 silver badges 2 2 bronze badges the only issue with ToolStripMenuItem is that it is not a Control and your code won't work. ;( Commented May 13, 2011 at 13:57 Actually this answer is closer to the question to me. Commented Jul 11, 2014 at 8:54

Assuming you have the menuStrip object and the menu is only one level deep, use:

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

For deeper menu levels add more SelectMany operators in the statement.

if you want to search all menu items in the strip then use

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

However, make sure each menu has a different name to avoid exception thrown by key duplicates.

To avoid exceptions you could use FirstOrDefault instead of SingleOrDefault / Single , or just return a sequence if you might have Name duplicates.

28.4k 15 15 gold badges 81 81 silver badges 103 103 bronze badges answered May 11, 2011 at 16:50 dmihailescu dmihailescu 1,633 17 17 silver badges 15 15 bronze badges

This should be the right solution. Other people did not know that ToolStripMenuItem is not control. Due to this reason their solutions do not work for ToolStripMenuItem.

Commented Jun 29, 2022 at 6:22
Control GetControlByName(string Name)

Disregard this, I reinvent wheels.

answered Oct 8, 2009 at 9:53 user47322 user47322 More of a general-purpose-ish solution than Julien's. Still works fine though. Commented Oct 8, 2009 at 9:57

this is not reinventing the wheel, it's a good solution that can be easily adapted to the case where you don't know a control's name or want to view the names of each control or do many things accessing controls, and was thus useful to me.

Commented Apr 20, 2016 at 8:17

Using the same approach of Philip Wallace, we can do like this:

 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; > 
 public void doSomething()
1 1 1 silver badge answered Oct 23, 2016 at 17:47 oviniciusfeitosa oviniciusfeitosa 1,015 1 1 gold badge 12 12 silver badges 12 12 bronze badges

One of the best way is a single row of code like this:

In this example we search all PictureBox by name in a form

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

Most important is the second paramenter of find .

if you are certain that the control name exists you can directly use it:

 PictureBox picSample = (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0]; 
answered Nov 29, 2017 at 8:06 daniele3004 daniele3004 13.7k 13 13 gold badges 73 73 silver badges 78 78 bronze badges

You can use find function in your Form class. If you want to cast (Label) ,(TextView) . etc, in this way you can use special features of objects. It will be return Label object.

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

name: item name of searched item in the form

true: Search all Children boolean value

answered Aug 2, 2019 at 12:07 Ferhat KOÇER Ferhat KOÇER 4,005 2 2 gold badges 27 27 silver badges 26 26 bronze badges

this.Controls.Find(name, searchAllChildren) doesn't find ToolStripItem because ToolStripItem is not a Control

 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)); >> > 
answered Jul 13, 2010 at 11:56 1,084 13 13 silver badges 23 23 bronze badges
this.Controls["name"]; 

This is the actual code that is 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; > > 
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; > 
answered Oct 28, 2009 at 18:33 Philip Wallace Philip Wallace 7,985 3 3 gold badges 29 29 silver badges 40 40 bronze badges what is ClientUtils.IsSecurityOrCriticalException ? Commented Jun 12, 2019 at 10:21

Assuming you have Windows.Form Form1 as the parent form which owns the menu you've created. One of the form's attributes is named .Menu . If the menu was created programmatically, it should be the same, and it would be recognized as a menu and placed in the Menu attribute of the Form.

In this case, I had a main menu called File . A sub menu, called a MenuItem under File contained the tag Open and was named menu_File_Open . The following worked. Assuming you

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