0

My control "MyTextBox1" add dynamically on form1 under container1 control. This form1 can be child of form2 and form2 can be child of form3 and so on how can I find my control from multi controls collection?

e.g. MyTextBox1 exists in

form3.form2.form1.Container1.MyTextBox1

how to find my control by name from multi control collections?

I do not want to use recursive foreach control collection. I am looking for an smart/short code like controls.Find().

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
Haseeb
  • 746
  • 7
  • 22
  • 1
    Most have a `Controls` property, but it's not always that easy: Take `SplitContainer` for example, which has `Panel1` and `Panel2` instead. – marsze Nov 13 '18 at 13:56
  • 1
    _I do not want to use recursive foreach control collection._ - ultimately that's what you will end up doing. You have to search the root control's control collection and then for each control in that collection search it's children until you find what you are looking for or have no more controls to search for. You could easily encapsulate it in a helper function or even an extension method. – Matt Burland Nov 13 '18 at 13:56
  • 1
    https://stackoverflow.com/questions/3419159/how-to-get-all-child-controls-of-a-windows-forms-form-of-a-specific-type-button – Dmitry Bychenko Nov 13 '18 at 13:57
  • Probably the easier solution might be, since you are adding the control dynamically, to just _keep the reference to the control you are adding_ somewhere. Then you won't have to find it again. – Matt Burland Nov 13 '18 at 13:57
  • 1
    Possible duplicate of [How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?](https://stackoverflow.com/questions/3419159/how-to-get-all-child-controls-of-a-windows-forms-form-of-a-specific-type-button) – marsze Nov 13 '18 at 13:57
  • Probably a XY question. How exactly do you "dynamically" add your control? You should be more specific about that and include an example. it seems you don't keep track of the added control and then try to find it by name instead. – marsze Nov 13 '18 at 14:16
  • Well, do use Controls.Find(). Pass *true* for the searchAllChildren argument. If you get nothing then that control does not have the Name property you expect, that happens. – Hans Passant Nov 13 '18 at 14:26

1 Answers1

1

If you don't want to put it recoursive, you can try BFS (Breadth First Search); let's implement it as an extension method:

public static class ControlExtensions { 
  public static IEnumerable<Control> RecoursiveControls(this Control parent) {
    if (null == parent)
      throw new ArgumentNullException(nameof(parent));

    Queue<Control> agenda = new Queue<Control>(parent.Controls.OfType<Control>());

    while (agenda.Any()) {
      yield return agenda.Peek();

      foreach (var item in agenda.Dequeue().Controls.OfType<Control>())
        agenda.Enqueue(item);
    }
  }
}

Then you can use it as

// Let's find Button "MyButton1" somewhere on MyForm 
// (not necessary directly, but may be on some container)
Button myBytton = MyForm
  .RecoursiveControls()
  .OfType<Button>()
  .FirstOrDefault(btn => btn.Name == "MyButton1");
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • thanks for answer. there are some controls do not have controls-collection instead have a Controls property, like SplitContainer which has Panel1 and Panel2 and these panels have child controls. in that case above code does not work. can we cover this gap in your code please? – Haseeb Nov 13 '18 at 14:35
  • @Haseeb: I've tried the code over a `Button` on a `Panel` which is on `SplitContainer`; it does work. Actually `SplitContainer` being a `Control` has `Controls` property. – Dmitry Bychenko Nov 13 '18 at 14:46
  • Many thanks let me check i will test and post my feedback comments here – Haseeb Nov 13 '18 at 16:39