It looks like a feature of the ControlCollection. In fact the docs say
that this class "enables ASP.NET server controls to maintain a list of
their child controls".

This is a rather specific description, and doesn't necessarily imply
that you can use the collection as an arbitrary container of references
to controls.  Presumably the ControlCollection sets the Control's
Controls property when you add a Control.  (Which it would have to - if
you create a new control and add it to a ControlCollection on a web
form, you would expect the control to join the control hierarchy.)

So I think the solution is, quite simply, not to use that class.  Use
ArrayList instead.  Or if you prefer, create an alternate type-safe
collection class that is designed to contain controls without also
supplying ASP.NET control hierarchy specific behaviour.


-- 
Ian Griffiths
DevelopMentor

-----Original Message-----
From: Bryan, Jason (Contractor) [mailto:[EMAIL PROTECTED] 

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