Hi all!

I am trying to discover and place into a ControlCollection all the controls
on a web page that match a particular type or begin with a particular name.
To do this, I've written a function that will go through the
ControlCollection passed to it and add the controls that match the condition
to another ControlCollection, as shown:

private System.Web.UI.ControlCollection FindControls(string ControlName,
System.Web.UI.ControlCollection ControlSet)
{
        System.Web.UI.ControlCollection retval = new
System.Web.UI.ControlCollection(new System.Web.UI.Control());
        foreach (System.Web.UI.Control thing in ControlSet)
        {
                if (thing.ID != null)
                        if (thing.ID.StartsWith(ControlName))
                                retval.Add(thing);
                if (thing.HasControls())
                        FindControls(ControlName, thing.Controls, ref
retval);
        }
        return retval;
}

private void FindControls(string ControlName,
System.Web.UI.ControlCollection ControlSet, ref
System.Web.UI.ControlCollection retval)
{
        foreach (System.Web.UI.Control thing in ControlSet)
        {
                if (thing.ID != null)
                        if (thing.ID.StartsWith(ControlName))
                                retval.Add(thing);
                if (thing.HasControls())
                        FindControls(ControlName, thing.Controls, ref
retval);
        }
}

When I try running this, the following exception is thrown:

"The list that this enumerator is bound to has been modified. An enumerator
can only be used if the list doesn't change."

With a stack trace of:

[InvalidOperationException: The list that this enumerator is bound to has
been modified. An enumerator can only be used if the list doesn't change.]
   System.Web.UI.ControlCollectionEnumerator.MoveNext() +112
   cs.webcontrols.FindControls(String ControlName, ControlCollection
ControlSet, ControlCollection& retval) in
c:\inetpub\wwwroot\cs\webcontrols.cs:75
   cs.webcontrols.FindControls(String ControlName, ControlCollection
ControlSet) in c:\inetpub\wwwroot\cs\webcontrols.cs:67
   cs.webcontrols.Page_Load(Object sender, EventArgs e) in
c:\inetpub\wwwroot\cs\webcontrols.cs:28
   System.EventHandler.Invoke(Object sender, EventArgs e) +0
   System.Web.UI.Control.OnLoad(EventArgs e) +67
   System.Web.UI.Control.LoadRecursive() +35
   System.Web.UI.Page.ProcessRequestMain() +731

When I trace through, the error occurs when I hit the first match, do a
.Add, and loop around for the next control.  So, I put more watches on the
variables around what .NET claimed was the offending line.  I watched it run
through and found that when the .Add method was called, it didn't copy a
reference to the control as I would have expected...it MOVED the control
from the parent ControlCollection to the new ControlCollection.

So, I tried to fool .NET by adding a function:

private void addControl(System.Web.UI.Control inControl, ref
System.Web.UI.ControlCollection retval)
{
        retval.Add(inControl);
}

and I change from calling .Add to:

                addControl(thing, ref retval);

thinking that because I was passing copies, .NET wouldn't be able to modify
the original.

Wrong.

I ran the modified code and watched .NET do the same thing all over again.

So...what is going on??  It appears that System.Web.UI.ControlCollection(s)
passes a pointer and not a copy.  To add to that, the only way to copy this
class is by calling the ".CopyTo" method which puts the control into a
System.Array.  This doesn't seem right either.

I must be going about this the hard way.  Anyone have any suggestions or
ideas?

TIA!
Jason Bryan

Reply via email to