-1

Im looking for a way to group a number of controls in Winforms by name using C#.

The best way I can describe the functionality I need is to compare it to how classes work in HTML/CSS where the same class is recycled throughout to target only the controls that are associated with that class.

I have tried using the name property from Control.Name but this hasnt worked out as planned.

Example

//Group controls by a group identifier in this case the string 'name'`
txtForename.name = "name";
txtSurname.name  = "name";
txtNotAName.name = "notAName";

foreach (Control control in form.Controls)
{
   if (control.Name == "name")
   {
      Console.WriteLine("true");
   }
}

Expected output

true;
true;

If more than one control has the same name, can I target them while searching a collection of controls?

Is this even possible?

Santhos
  • 3,348
  • 5
  • 30
  • 48
Master Yoda
  • 4,334
  • 10
  • 43
  • 77

2 Answers2

2

You could use the Tag property on the controls which can store any object. Your code would then be:

foreach (Control control in form.Controls)
{
  if(control.Tag != null && control.Tag.ToString() == "myTag")
  {
     //...
  }
}

Alternatively, you could use System.Linq to omit the inner if clause:

foreach (Control in form.Controls.Cast<Control>().Where(c => c.Tag != null && c.Tag.ToString() == "myTag"))
{
  //...
}
Santhos
  • 3,348
  • 5
  • 30
  • 48
  • Hey Santhos, thanks for the answer, I have had a look at the ControlsCollection object in C# and there does not seem to be a Where() method available. I will try the tag property on what i have already. – Master Yoda Apr 22 '15 at 15:28
  • `control.Tag.ToString()` will throw NullReferenceException for controls which has default Tag (null) – ASh Apr 22 '15 at 15:28
  • @KyleT: Where is an extension method of System.Linq namespace, write using System.Linq; at the beginning of your .cs file – Santhos Apr 22 '15 at 15:29
  • @ASh: yes that is true, but if you look at the question, he fills in all the Name properties. I assume he would do that for all the Tag properties as well, but I will fix my code for you. – Santhos Apr 22 '15 at 15:31
  • @Santhos Yes i included that, the ControlsCollection class inherits from the following: ControlCollection : ArrangedElementCollection, IList, ICollection, IEnumerable, ICloneable. Could this be the cause? It works fine with a list. – Master Yoda Apr 22 '15 at 15:32
  • @KyleT: Where() should work on all IEnumerable collections, https://msdn.microsoft.com/en-us/library/vstudio/bb534803%28v=vs.100%29.aspx – Santhos Apr 22 '15 at 15:34
  • I have also found this SO question where they seem to be speaking about a similar, maybe the same thing you are trying to do: http://stackoverflow.com/questions/2024607/finding-a-control-on-a-winforms-using-linq – Santhos Apr 22 '15 at 15:37
  • @Santhos Ill post an image on the question of the error. – Master Yoda Apr 22 '15 at 15:38
  • 1
    @KyleT just use `form.Controls.Cast().Where` and so on. – Andrey Korneyev Apr 22 '15 at 15:43
  • Sorry, my mistake, Andy is right and you were also right KyleT. It is because the ControlCollection is just IEnumerable, not a generic IEnumerable (or IEnumerable in this case). Using the cast can possibly raise an exception if there was a control that cannot be cast to Control class. However, that never happens in this case. – Santhos Apr 22 '15 at 15:56
0

Since you have controls in the form and in containers, recursion comes to mind to find them.

    public static void Test()
    {
        //Group controls by a group identifier in this case the string 'name'`
        TextBox txtForename = new TextBox();
        TextBox txtSurname = new TextBox();
        TextBox txtNotAName = new TextBox();

        GroupBox groupBox = new GroupBox();
        groupBox.Controls.Add(txtSurname);

        txtForename.Name = "name";
        txtSurname.Name = "name";
        txtNotAName.Name = "notAName";

        Form form1 = new Form();
        form1.Controls.Add(txtForename);
        form1.Controls.Add(txtNotAName);
        form1.Controls.Add(groupBox);

        DisplayControlsByName(form1, "name");

        Console.ReadLine();
    }

    private static void DisplayControlsByName(Control searchControl, string name)
    {
        foreach (Control control in searchControl.Controls)
        {
            if (control.Name == name)
            {
                Console.WriteLine("true");
            }

            if (control.Controls.Count > 0)
            {
                DisplayControlsByName(control, name);
            }
        }
    }

Results:

enter image description here

Can you show more of your code, so could see what else may be happening?

Shar1er80
  • 9,001
  • 2
  • 20
  • 29
  • I agree. I thought the code wouldn't even run, but it did. – Shar1er80 Apr 22 '15 at 15:29
  • @Shar1er80 I figured out whats going wrong with that code, its because the controls collection for some reason only returns some of the controls i.e. container controls like panels, groupboxes which have their own collections i will have to query. – Master Yoda Apr 22 '15 at 15:35