How do I access asp.net controls that are nested multiple levels in a page from a custom validator?
Specifically, I am generating dropdownlists that are inside a placeholder, which is inside a repeater, which is inside of another repeater, which is inside of another placeholder.
I need to access the selected values of all of the drop down boxes to compare to one another.
My current solution is to loop through all of the controls inside each control, until I get down deep enough to access the dropdownlist’s:
For Each g As Control In sender.Parent.Controls
If g.GetType().ToString.Equals("System.Web.UI.WebControls.Repeater") Then
For Each k As Control In g.Controls
If k.GetType().ToString.Equals("System.Web.UI.WebControls.RepeaterItem") Then
For Each l As Control In k.Controls
If l.GetType().ToString.Equals("System.Web.UI.WebControls.Repeater") Then
For Each p As Control In l.Controls
If p.GetType().ToString.Equals("System.Web.UI.WebControls.RepeaterItem") Then
For Each n As Control In p.Controls
If n.GetType().ToString.Equals("System.Web.UI.WebControls.PlaceHolder") Then
For Each c As Control In n.Controls
If c.GetType().ToString.Equals("System.Web.UI.WebControls.DropDownList") Then
'Add the dropdownlist to an array so that I can use it after all drop down lists have been added for validation.
This seems like an entire waste of resources. Is there a better way to access these controls from the custom validator?
I believe you can use
$to concatenate container names to access a nested control; something like this:This does result in an internal
FindControl()call to be performed by the validator which is somewhat expensive so you should use this approach sparingly.In general, it’s not a very good idea to access deeply nested controls inside other containers. You should treat these controls as private members of a page / control and not access them this way. Only use the above approach if you really, really must.
Edit: this may not be the perfect solution but I’d do it this way. Create a new DropDownListX control (derives from DropDownList) that grabs the page and checks if the page implements a new custom interface that you create. This interface can be used to register a control with the page and then your validator can go through this list and validate each registered control. Something like:
Your page should implement this interface. Then in your new DropDownListX control:
Then in the page, when validation happens, you can go through the list of controls in the validation list and validate them one by one. Your custom validator won’t have a single
ControlToValidatecontrol name but that seems appropriate for you, since you have 1 validator that validates multiple controls inside nested repeaters.This solution gives you the ability to completely skip your current deep loop – if you have a control that needs validation, it’ll register itself, otherwise the list in the page will be empty and nothing needs to be checked. This also avoids doing string comparisons for control names since controls don’t need to be searched – they register themselves when they need to.