0

I have added few controls to a table and added that table to a panel. Now, I want to access those controls(like text boxes, dropdowns etc..) in another method. I am trying as

List<Control> panelControls = (from pControls in _controlsPanel.Controls.OfType<Table>(). OfType<TableRow>().OfType<TableCell>().OfType<Control>()
                                              .Where(ctrl => (ctrl is TextBox || ctrl is DropDownList))
                                           select pControls).ToList();

which is evudently giving me no controls I added to table and eventually to panel.

Should I add each of the control in my table to Panel or is there a better way to retrieve the controls?

Because, I thought, since all the controls are in a table , it seemed redundant to me to add controls again to panel explicitly. However I might be wrong. please clarify.

Programmerzzz
  • 1,237
  • 21
  • 48

1 Answers1

1

You seem to have mixed query and method syntax which is making my head hurt. For the purposes of my answer I'll stick to method syntax.

In your LINQ, you are starting with a single list (pControls) and applying several OfType and Where clauses, each of which will filter the list. Thus you are saying "Give me all controls that are tables and are table rows and are textboxes or dropdownlists." There is no object that is both a table and a table row at the same time, so right there you're going to get an empty list.

instead, you have to walk the hierarchy a bit. You need to generate a list (e.g. of tables), then use items in that list to get another list (controls that belong to those tables).

If you want to get all the controls on a single panel, you just use

var panelControls = pControls.Controls;

If you want to get all the controls from a single table, first get a reference to the table. For example, if your table is named MyTable:

var table = pControls.Controls.OfType<Table>().Where( c => c.ID == "MyTable").First();

Then use that reference to get the controls:

var controls = table.Controls;

or if you want it all in one statement:

var controls = pControls.Controls
                        .OfType<Table>()
                        .Where( c => c.ID == "MyTable")
                        .First()
                        .Controls;

You can then filter that list just to get textboxes or dropdownlists:

var list = controls.OfType<Control>().Where( c => c is TextBox || c is DropDownList);

Or, if you really want it all in one statement:

var list = pControls.Controls
                    .OfType<Table>()
                    .Where( c => c.ID == "MyTable")
                    .First()
                    .Controls
                    .OfType<Control>()
                    .Where( c => c is TextBox || c is DropDownList);
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Thanks John for the pointers its very close, but what if my table ID is dynamically generated and I don't know it. – Programmerzzz May 31 '17 at 03:46
  • If there is only one table, just eliminate the where clause. If there are several tables and you want to combine them, you'll have to use a `ForEach` approach and iterate over each table's controls separately. – John Wu May 31 '17 at 03:48
  • I did that but its just giving some error saying that the last `where` doesn't have a definition. Just as an FYI, I am adding textboxes to TableCell and those TableCells to TableRow and TableRows to Table and eventually Table to Panel. `TextBox/DropDowns-->TableCell-->TableRow-->Table-->Panel` – Programmerzzz May 31 '17 at 04:08
  • *Some error*? Well then I suggest *some solution*. ;) Sorry but you should know better. – John Wu May 31 '17 at 04:09
  • Ohh sorry, the error is `Controls Collection does not contain definition for Where and no extension method Where accepting first argument of type ControlCollection`. – Programmerzzz May 31 '17 at 04:16
  • Oops, looks like I ran into [this problem](https://stackoverflow.com/questions/3302435/why-doesnt-the-controls-collection-provide-all-of-the-ienumerable-methods). Easy to fix by adding `OfType`. Edited. – John Wu May 31 '17 at 18:00