Reference one control from another control while within a Repeater (or DataGrid)

I have a dropdownlist (aka drop down list) box within a repeater.  When the index change event fires, I want to make some changes in another control.  The problem in doing this was that I could not figure out how I could reference another control.  Well, thanks to Scott Mitchell's articles on the datagrid, I was able to figure this out.  First, all my repeater elements were editable, so everything was setup within an ItemTemplate column.  This only caused me issues in my thinking about it, not in my doing.  So, within my SelectedIndexChanged event, I have the following code:

Dim ddl1 as DropDownList = CType(sender, DropDownList)
Dim rpItem as RepeaterItem = CType(ddl1.Parent, RepeaterItem)
Dim ddl2 as DropDownList = CType(rpItem.FindControl("ddl2"), DropDownList)

Now, I have the reference to the second control. 

One question, since FindControl() is fairly CPU intensive, is there a better way to do this?

Wally

6 Comments

  • Within a DataGrid you can access the control via the indexer:



    DropDownList ddl2 = (DropDownList) DataGrid1.Controls[0].Controls[1];



    Not sure if you can or how with a Repeater? But this is definatly faster than .FineControl

  • i dont know if FindControl is really CPU intensive or not, my understanding is a simple walk through of the current Naming Container's controls collection looking for the given ID.



    Granted, not as elegant as being able to immediately reference the control, but that's ASP.Net for you (when you bury them inside containers)

  • I wouldn't worry about the "CPU intensiveness" about FindControl(). We use it in plenty of places I haven't seen any adverse effects.



    I am interested in how you are measuring FindControl to be CPU intensive though.

  • CPU intensive was probably the wrong word to use. I have always heard that while FindControl() works, it is relatively slow.



    Wally

  • I'd say that's definitely the way to do it (the way you posted). Although you don't need to use a CType on ddl1.Parent since you can call FindControl directly on Parent, but that's no biggie.



    I would always stay away from accessing controls by index. Sure, it's slightly faster than calling FindControl, but as soon as you put a space that didn't used to be there or add in some other controls it will break your code and for pretty much no performance cost, it's not worth it.



    My understanding of FindControl is that it just uses recursion to go through all the controls (and all their children recursively...if i'm wrong on child control searching, sorry) until it finds one that matches the ID you specified. I really don't see how a simple boolean check in a recursive loop could really be very CPU intensive. I wouldn't worry about it.



    Also, there's some neat things you can do with Parent. I've used it in the past on embedded repeaters to where you can actually have a child repeater walk back up to it's parent repeater (using e.Item.Parent.Parent.FindControl) and get a control and set or get values. Sure you could over do it, but pretty neat! ;)



    Man I'm rambling, but one more thing...I'd recommend you use DirectCast instead of CType. There are times to use CType, but in your example it isn't necessary. CType is basically "Change Type" where DirectCast is just casting the object (which is what you're doing in this case). My understanding is that if you're casting to the same type though, it's really just adding an extra boolean evaluation, so it's so minor of a difference you're really not going to notice it, but still :P I pretty much always use DirectCast unless I actually need to change the type of the variable. Alright, alright, I'll shut up! :P

  • Note: I have not tested this myself.

    I would imagine FindControl() would cause a considerable performance hit because it must iterate through each control on a page. Granted, this might not be much of a task for many of the servers today, but you have to think:

    1) If there are a lot of controls on a page, such as any page with a repeater or datagrid (each row would be its own control), it has to iterate through each one in the enumeration.
    2) It must cast them to a generic control (probably WebControl) to check its ID or ClientID.
    3) Once cast, it must compare the ID or ClientID space in memory vs. the string in FindControl().
    4) If it matches, return the memory reference of the enumerated control.

    By referencing the control itself, we already know the place in memory that control resides.

    Again, I have not tested this, but it seems logical that FindControl() would be a huge memory hog. Anyone know for sure?

Comments have been disabled for this content.