Fabio Lolli
Fabio Lolli

Reputation: 889

C#: Get all the controls with runat="server"

I have a lot of .aspx pages with a lot of controls. These controls are all declared in a similar way:

<input type="text" runat="server" id="txtLatitude" />

Now I have to check who the user is and, if not allowed to make changes, make all these controls readonly. Normally i would do somethink like

txtLatitude.Attributes.Add("readonly", "readonly")

but it would take me forever to do that manually for each control in each page. I was wondering if there is a way to get a List or something of all the controls with runat="server". I tried using

ControlCollection myControls = Page.Controls

to get them, but I looked at myControls in debug mode and it seems to get a small number of controls, maybe only the controls declared with the asp specific notation , not sure about it.

With said List i would simply do a foreach cycle and add the readonly attribute to each, with a few lines of code. Ideas? (Or maybe I'm just dumb and wasn't able to navigate and search trough myControls in the right way =D )

Upvotes: 2

Views: 1779

Answers (3)

Jay Douglass
Jay Douglass

Reputation: 4918

Apologies for VB.NET. I do this with some extension methods. You also need to pick up an Each extension method on IEnumerable from nuget (try MoreLinq):

    ''' <summary>
    ''' Returns the control and all descendants as a sequence
    ''' </summary>
    <Extension>
    Public Iterator Function AsEnumerable(control As Control) As IEnumerable(Of Control)
        Dim queue = New Queue(Of Control)
        queue.Enqueue(control)

        Do While queue.Count <> 0
            control = queue.Dequeue()
            Yield control
            For Each c As Control In control.Controls
                queue.Enqueue(c)
            Next
        Loop
    End Function

    <Extension>
    Public Sub SetInputControlsToReadonly(control As Control)
        control.AsEnumerable().Each(Sub(c)
                                        If TypeOf c Is TextBox Then DirectCast(c, TextBox).ReadOnly = True
                                        If TypeOf c Is ListControl Then DirectCast(c, ListControl).Enabled = False
                                    End Sub)
    End Sub

This allows you to call control.SetInputControlsToReadonly(). Sometimes you don't want to set all controls to readonly, only a section on the page. In this case wrap the controls in a (or use a Panel), and call SetInputControlsToReadonly on that.

Upvotes: 0

User2012384
User2012384

Reputation: 4919

Add this function on your page:

void whatYouWannaDo (Control con)
{
    foreach (Control c in con.Controls)
    {
      if (c.Controls.Count > 0)
          whatYouWannaDo(c);
      else
         {
           //Do stuff here
         }
    }
}

You can do whatever you want in this recursive function. and call this by putting whatYouWannaDo(Page.Controls)

Upvotes: 0

Robert McKee
Robert McKee

Reputation: 21487

Taken from: Get All Web Controls of a Specific Type on a Page

/// <summary>
/// Provide utilities methods related to <see cref="Control"/> objects
/// </summary>
public static class ControlUtilities
{
    /// <summary>
    /// Find the first ancestor of the selected control in the control tree
    /// </summary>
    /// <typeparam name="TControl">Type of the ancestor to look for</typeparam>
    /// <param name="control">The control to look for its ancestors</param>
    /// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns>
    public static TControl FindAncestor<TControl>(this Control control) where TControl : Control
    {
        if (control == null) throw new ArgumentNullException("control");

        Control parent = control;
        do
        {
            parent = parent.Parent;
            var candidate = parent as TControl;
            if (candidate != null)
            {
                return candidate;
            }
        } while (parent != null);
        return null;
    }

    /// <summary>
    /// Finds all descendants of a certain type of the specified control.
    /// </summary>
    /// <typeparam name="TControl">The type of descendant controls to look for.</typeparam>
    /// <param name="parent">The parent control where to look into.</param>
    /// <returns>All corresponding descendants</returns>
    public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control
    {
        if (parent == null) throw new ArgumentNullException("control");

        if (parent.HasControls())
        {
            foreach (Control childControl in parent.Controls)
            {
                var candidate = childControl as TControl;
                if (candidate != null) yield return candidate;

                foreach (var nextLevel in FindDescendants<TControl>(childControl))
                {
                    yield return nextLevel;
                }
            }
        }
    }
}

Then do something like:

foreach(var ctrl in Page.FindDescendants<HtmlInputText>())
{
    ctrl.Attributes.Add("readonly","readonly");
}

Upvotes: 1

Related Questions