views:

334

answers:

2

I have quite complicated set of HTML that I want to trawl looking for inputs that match various criteria. I hope to use something along the lines of:

private void setup()
{
    masterContainer.InnerHtml = @"
    <div>crazy
        <div>unknown
            <div>html layout
                <select id='crazySelectIdentifier_id1' runat='server'>
                    <option value='1'>Item1</option>
                    <option value='2'>Item2</option>
                </select>
            </div>
        </div>
    </div>
    <div>
        <div>
            <select id='crazySelectIdentifier_id2' runat='server'>
                <option value='1'>Item1</option>
                <option value='2'>Item2</option>
            </select>
        </div>
    </div>
    <div>
    </div>";
}

private void recursiveTrawl(HtmlGenericControl currentOuterControl)
{                            
    for (int i = 0; i < currentOuterControl.Controls.Count; i++)
    {
        HtmlGenericControl currentControl = (HtmlGenericControl) currentOuterControl.Controls[i];
        if(currentControl.HasControls())
        {
            recursiveTrawl(currentControl);
        }
        else
        {
             String[] controlArr = currentControl.ID.ToString().Split('_');
             String currentId = controlArr[1];

             if (currentId.Equals("somethingspecific"))
             {
                  //THE PROBLEM IS HERE
                  DropDownList dropdown = (DropDownList)currentControl;

However, I get the error- Cannot convert type 'System.Web.UI.HtmlControls.HtmlGenericControl' to 'System.Web.UI.WebControls.DropDownList'

I've tried using HtmlSelect as well with a similiar error. I just need to know how I can get access to the selected values in the drop down lists I'm interested in.

Thanks in advance.

+1  A: 

Try this:

WebForm

<asp:PlaceHolder ID="PlaceHolder1" runat="server" />

Extension Method

public static class ControlExtensions
{

    public static void FindControlByType<TControl>(this Control container, ref List<TControl> controls) where TControl : Control
    {
        if (container == null)
            throw new ArgumentNullException("container");

        if (controls == null)
            throw new ArgumentNullException("controls");

        foreach (Control ctl in container.Controls)
        {
            if (ctl is TControl)
                controls.Add((TControl)ctl);

            ctl.FindControlByType<TControl>(ref controls);
        }
    }

}

Code

string html = @"<div>
                    <select id='Sel1' runat='server'>
                        <option value='1'>Item1</option>
                        <option value='2'>Item2</option>
                        <option value='3'>Item3</option>
                    </select>
                </div>
                <div>
                    <select id='Sel2' runat='server'>
                        <option value='4'>Item4</option>
                        <option value='5'>Item5</option>
                        <option value='6'>Item6</option>
                    </select>
                </div>";

Control ctl = TemplateControl.ParseControl(html);
PlaceHolder1.Controls.Add(ctl);

List<HtmlSelect> controls = new List<HtmlSelect>();
PlaceHolder1.FindControlByType<HtmlSelect>(ref controls);

foreach (HtmlSelect select in controls)
{
}
Mehdi Golchin
No, I do not wish to generate the DropDown. It's already generated and on the page. And I can locate it. But when I locate it, it's a HtmlGenericControl. I need to be able to convert it to something useful like a DropDownList or a HtmlSelect.
Tom
How did you make the DropDownList(already put a simple <select... tag which marked as runat="server" or an ASP.NET DropDownList or an auto generated one)?
Mehdi Golchin
written html with runat="server"
Tom
Have you written something like `<select id="Sel1" runat="server"><option value="1">Item1</option>...</select>`? If so, it's really an HTMLSelect. Can you explain more with code?
Mehdi Golchin
Thanks for your help so far Mehdi.I've changed my example now to make my initial setup clearer. I have a html tree, there will be select inputs in the html. But I don't know where they are or their exact IDs. So I can go through the html tree, testing everything I find to see if it matches my criteria. But once I've found it, I need to get access to its SelectedValue for instance. But to do this I need to convert the HtmlGenericControl to a HtmlSelect.
Tom
I don't know what you are going to do. Anyway, I've updated my answer. Hope this helps.
Mehdi Golchin
Thanks Mehdi, but no, that won't work. I cannot use FindControl as I don't know the specific IDs of the controls I'm interested in.
Tom
I've updated the code. I added a new extension method named `FindControlByType` that finds the controls by their type. Thus, you can find the desired controls in the hierarchial structure.
Mehdi Golchin
+1  A: 

This cast will always error at compile time because there's no inheritance relationship between HtmlGenericControl and HtmlSelect. An object cannot be both. Once an object has been successfully cast as HtmlGenericControl (as the function argument is), the compiler knows for certain that it can't also be a HtmlSelect, so it won't let you even try the cast.

Even if the compile worked, you would get an error at runtime, because the <select> is not a HtmlGenericControl.

Your solution is not to bother casting anything to HtmlGenericControl. Just use the Control class, as it comes out of the Controls collection. The only cast you should do is to HtmlSelect, when you know you're looking at the right object.

Auraseer