AshOoO
AshOoO

Reputation: 1148

Get a control by reflection

I need to get a control [textbox,label,button ...etc] from my page by it's ID using reflection

In my case I have a class that all other system pages inherit from it and this class is override the onload event to change some properties to some controls

like set the visibility state for textbox by it's name but as I don't have the control direct on the page as I may have it on content place holder in master page so I couldn't use findcontrol method also I think recursive function to find the control will take too much time

So I try to do it with refelection to find a control with its name then change the visable or enable state for it

I used the FieldInfo class but doesn't work with me

FieldInfo fi = this.GetType().GetField("ControlID", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);

Any help !

Upvotes: 3

Views: 4834

Answers (3)

abatishchev
abatishchev

Reputation: 100308

Here's very useful extension method to get child controls recursively:

public static IEnumerable<Control> GetChildControls(this Control control)
{
    var children = (control.Controls != null) ? control.Controls.OfType<Control>() : Enumerable.Empty<Control>();
    return children.SelectMany(c => GetChildControls(c)).Concat(children);
}

Usage:

IEnumerable<Control> allChildren = parent.GetChildControls();

Upvotes: 0

peteisace
peteisace

Reputation: 2772

maybe you need to recursively look for your control with FindControl, and then calling itself?

private static Control FindNestedControl(string id, Control parent)
{
    Control item = parent.FindControl(id);

    if(item == null) 
    {
        foreach(var child in parent.Controls)
        {
            item = child.FindNestedControl(id, child);

            if(item != null)
            {
                return item;
            }
        }
    }

    return null;
}

And call it passing the current instance of the page through:

Control item = FindNestedControl("bob", this);

This can be slow however - so do look out for that if there's a whole bunch of controls on the page :)

Another way to do it would be simply expose the controls as properties in your base class:

public abstract class BasePage : Page
{
    #region Properties

    /// Gets the textbox for editing in derived classes.
    protected TextBox SomeTextBox
    {
       return this.textBox; }
    }

    #endregion

}

And the final way to do it would be to hook into derived classes in your base class:

public abstract class BasePage : Page
{
        /// <summary>
        /// Called when loading the page.
        /// </summary>
        /// <param name="e">The event arguments.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // Do some basic setup.

            // Now pass the controls to the derived classes.
            this.ConfigureControl(this.mainText);
            this.ConfigureControl(this.nameDropDown);
            this.ConfigureControl(this.someOtherControl);            
        }

        /// <summary>
        /// Provides hook for derived classes.
        /// </summary>
        /// <param name="control">The core control.</param>
        protected virtual void ConfigureControl(Control control)
        {
        }
 }

And then override in your derived page:

protected override void ConfigureControl(Control control)
{
    switch(control.ID) 
    {
        case "mainText":
        TextBox mainText = (TextBox)control;
        mainText.Text = "works";
        break;
    }
}

Out of these i would probably use the second if there's not so many controls. The first method is useful when dealing with repeaters and the like.

Upvotes: 1

Stecya
Stecya

Reputation: 23266

Have you tried FindControl

  Control myControl = this.FindControl("TextBox2");
  if(myControl !=null)
  {
       // Do Stuff
  }

Upvotes: 7

Related Questions