asp.netnullreferenceexceptionfindcontrolhtmlgenericcontrol

asp.net find control inside runat div


I have this div in my markup

<form id="form1" runat="server">
    <div class="mt-5">
        <div id="d" runat="server"></div>
    </div>
</form>

I then add to it some html elements by codebehind:

string[] parole = { "morning", "good", "StackOverflow!" };
string[] ordinalID = { "2", "1", "3" };
string[] images = { "images/img-1.jpg", "images/img-2.jpg", "images/img-3.jpg" };

HtmlGenericControl unorderedList = new HtmlGenericControl("ul");
unorderedList.Attributes["class"] = "sortable-list";
unorderedList.Attributes["id"] = "sortable";
unorderedList.ClientIDMode = ClientIDMode.Static;


Int16 i = -1;
foreach (string parola in parole)
{
    ++i;
   
    HtmlGenericControl listItem = new HtmlGenericControl("li");
    listItem.Attributes["class"] = "item";
    listItem.Attributes["id"] = ordinalID[i];
    listItem.Attributes["draggable"] = "true";
    listItem.ClientIDMode = ClientIDMode.Static;

    HtmlGenericControl div = new HtmlGenericControl("div");
    div.Attributes["class"] = "details";

    HtmlGenericControl img = new HtmlGenericControl("img");
    img.Attributes["src"] = images[i];

    HtmlGenericControl span = new HtmlGenericControl("span");
    span.InnerText = parola;

    HtmlGenericControl info = new HtmlGenericControl("i");
    info.Attributes["class"] = "uil uil-draggabledots";

    div.Controls.Add(img);
    div.Controls.Add(span);
    listItem.Controls.Add(div);
    listItem.Controls.Add(info);
    unorderedList.Controls.Add(listItem);
}


d.Controls.Add(unorderedList);

At some point I need to retrieve the listItem element to change its class attribute, and I'm trying to do like this:

HtmlGenericControl ul = (HtmlGenericControl)d.FindControl("sortable");
HtmlGenericControl listItem = (HtmlGenericControl)ul.FindControl(ordinalID);
listItem.Attributes["class"] = "item bg-danger";

But gives me a null reference exception on ul element... how can I achieve what I want? Thanks!


Solution

  • This may not be a real answer, but shows why setting ID as attribute does not work and should be set as property.

    A few modifications to the original code:

    <form id="form1" runat="server">
        <div>
            <div class="mt-5">
                <div id="d" runat="server"></div>
            </div>
            <asp: Button ID="btn1" runat="server" Text="Check" OnClick="btn1_Click" />
            <asp: Label id="Lbl1" runat="server"></asp: Label>
        </div>
    </form>
    

    creating elements:

    string[] parole = { "morning", "good", "StackOverflow!" };
    string[] ordinalID = { "2", "1", "3" };
    string[] images = { "images/img-1.jpg", "images/img-2.jpg", "images/img-3.jpg" };
    
    void create_elements()
    {
        HtmlGenericControl unorderedList = new HtmlGenericControl("ul")
        {
            ID = "sortable",
            ClientIDMode = ClientIDMode.Static
        };
        unorderedList.Attributes.Add("class", "sortable-list");
    
        Int16 i = -1;
        foreach (string parola in parole)
        {
            ++i;
    
            HtmlGenericControl listItem = new HtmlGenericControl("li")
            {
                ID = ordinalID[i],
                ClientIDMode = ClientIDMode.Static
            };
            listItem.Attributes.Add("class" , "item");
            listItem.Attributes.Add("draggable" , "true");
    
            HtmlGenericControl div = new HtmlGenericControl("div");
            div.Attributes.Add("class", "details");
      
            HtmlGenericControl img = new HtmlGenericControl("img");
            img.Attributes.Add("src" , images[i]);
    
            HtmlGenericControl span = new HtmlGenericControl("span")
            {
                InnerText = parola
            };
    
            HtmlGenericControl info = new HtmlGenericControl("i");
            info.Attributes.Add("class", "uil uil-draggabledots");
    
            div.Controls.Add(img);
            div.Controls.Add(span);
            listItem.Controls.Add(div);
            listItem.Controls.Add(info);
            unorderedList.Controls.Add(listItem);
        }
        d.Controls.Add(unorderedList);
    }
    

    check:

    protected void btn1_Click(object sender, EventArgs e)
    {
        HtmlGenericControl ul = (HtmlGenericControl)d.FindControl("sortable");
        HtmlGenericControl listItem = (HtmlGenericControl)ul.FindControl(ordinalID[0]);
        listItem.Attributes.Add("class", "item bg-danger");
        Lbl1.Text=listItem.Attributes["class"];
    }
    

    inspecting shows the findcontrol now can find elements from ID: unorderedList

    listItem

    result: result