ASP.NET Is There a Better Way to Find Controls That Are Within Other Controls

Better way to find control in ASP.NET

If you're looking for a specific type of control you could use a recursive loop like this one -
http://weblogs.asp.net/eporter/archive/2007/02/24/asp-net-findcontrol-recursive-with-generics.aspx

Here's an example I made that returns all controls of the given type

/// <summary>
/// Finds all controls of type T stores them in FoundControls
/// </summary>
/// <typeparam name="T"></typeparam>
private class ControlFinder<T> where T : Control
{
private readonly List<T> _foundControls = new List<T>();
public IEnumerable<T> FoundControls
{
get { return _foundControls; }
}

public void FindChildControlsRecursive(Control control)
{
foreach (Control childControl in control.Controls)
{
if (childControl.GetType() == typeof(T))
{
_foundControls.Add((T)childControl);
}
else
{
FindChildControlsRecursive(childControl);
}
}
}
}

Finding controls that use a certain interface in ASP.NET

Longhorn213 almost has the right answer, but as as Sean Chambers and bdukes say, you should use

ctrl is IInterfaceToFind

instead of

ctrl.GetType() == aTypeVariable  

The reason why is that if you use .GetType() you will get the true type of an object, not necessarily what it can also be cast to in its inheritance/Interface implementation chain. Also, .GetType() will never return an abstract type/interface since you can't new up an abstract type or interface. GetType() returns concrete types only.

The reason this doesn't work

if(ctrl is typeToFind)  

Is because the type of the variable typeToFind is actually System.RuntimeType, not the type you've set its value to. Example, if you set a string's value to "foo", its type is still string not "foo". I hope that makes sense. It's very easy to get confused when working with types. I'm chronically confused when working with them.

The most import thing to note about longhorn213's answer is that you have to use recursion or you may miss some of the controls on the page.

Although we have a working solution here, I too would love to see if there is a more succinct way to do this with LINQ.

Get a control inside another control

I figured out what the problem was so I'll leave the question here for anyone who may have the same problem and stumble across this

I was so used to working with controls from a master page but within a page that's inside the master page you don't need the first findcontrol its simply:

protected void Register_Click(object sender, EventArgs e)
{
LoginView1.FindControl("LoginPanel").Visible = false;
LoginView1.FindControl("RegPanel").Visible = true;
}

A Better way? Finding ASP.NET controls, finding their id

Instead of using the Lambda expression I have created a method that handles the control for me, and depending on the name of the control, it sets that section to be true

public bool setGroup(Control ctrl)
{
isAControl = false;

//set a section to true, so it will pull the html
if (ctrl.ID.StartsWith("GenInfo_"))
{
GenInfo = true;
lstControls.Add(ctrl.ID.Replace("GenInfo_", ""));
isAControl = true;
return isAControl;
}

here is a small snippet of my code I only want to check for certain controls(to speed things up) and I go through each control as each control has a different way to get the value (textbox would use .text where dropdownlist would use .selectedValue)

if(control is TextBox || control is DropDownList || control is RadioButton || control is RadioButtonList 
|| control is CheckBox || control is CheckBoxList)
{
if (control is TextBox)
{
TextBox txt = control as TextBox;
if (txt.Text != "" && txt.Text != "YYYY/MM/DD")
{
setGroup(control);
if (isAControl)
{
string controlNoGroup = lstControls.Last();
strHtml = strHtml.Replace("@" + (controlNoGroup.ToString()) + "@", txt.Text);
}
}
}

Finding all controls in an ASP.NET Panel?

It boils down to enumerating all the controls in the control hierarchy:

    IEnumerable<Control> EnumerateControlsRecursive(Control parent)
{
foreach (Control child in parent.Controls)
{
yield return child;
foreach (Control descendant in EnumerateControlsRecursive(child))
yield return descendant;
}
}

You can use it like this:

        foreach (Control c in EnumerateControlsRecursive(Page))
{
if(c is TextBox)
{
// do something useful
}
}

find control in page

To find the button on your content page you have to search for the ContentPlaceHolder1 control first.
Then use the FindControl function on the ContentPlaceHolder1 control to search for your button:

 ContentPlaceHolder cph = (ContentPlaceHolder)this.Master.FindControl("ContentPlaceHolder1");
Response.Write(((Button)cph.FindControl("a")).Text);

Asp.net FindControl anywhere in under specific element

Declare an extension method like this:

public static class ControlExtensions
{

public static IEnumerable<Control> GetEnumerableChildren(this Control control)
{
return control.Controls.Cast<Control>();
}

public static Control FindAny(this Control control, string id)
{
var result = control.GetEnumerableChildren().FirstOrDefault(c => c.ID == id);

if (result != null)
return result;

return control.GetEnumerableChildren().Select(child => child.FindAny(id)).FirstOrDefault();
}
}

Then do:

var foundControl = e.Item.FindControl("tableHolder").FindAny("panelToFind");

Note will return null if no control exists with that id.

Better, stronger typed way of getting at controls in asp.net?

You can put all your controls into a strongly-typed custom control (including ASCX user controls) and only have to use FindControl() once:

CustomControl myControl= (CustomControl) e.Item.FindControl("oMyControl");

myControl.litCompanyName.Text = rd["CompanyName"].ToString();

How to find user control of an ASP.NET page inside of event of another user control on that ASP.NET page EDIT: different content placeholders?

Ok I found solution until better one comes my way. The problem is, as Jamie Dixon pointed out (thank you Jamie):

The FindControl method does not do a deep search for controls. It looks directly in the location you specify for the control you're requesting.

So because I have user controls in different contentplaceholders I must first find targeted placeholder (where the user control reside) and then I can search for user control inside it:

protected void Dodaj_Feed_Panel_Click(object sender, EventArgs e)
{
ContentPlaceHolder MySecondContent = (ContentPlaceHolder)this.Parent.Parent.FindControl("MyTestContent2");

UserControl UC_text = (UserControl)MySecondContent.FindControl("text1");
UC_text.Visible = true;
}

what really annoys and confuses me is the this.Parent.Parent part because I know it's not the best solution (in case I change the hierarchy a bit this code will break). What this part of code actually does is that it goes two levels up in page hierarchy (that is page where both user controls are). I don't know what the difference with this.Page is because for me it means the same but is not working for me.

Long term solution would be something like server side "jQuery-like selectors" (it can found elements no matter where they are in hierarchy). Anyone has a better solution?



Related Topics



Leave a reply



Submit