c# - error using FindControl on div id
Asked Answered
S

4

8

I have an ASP.NET site that I am trying to access div elements by their ID from the C# code behind file. Essentially I want to see if a div element exists, and if so, alter its properties.

I've found many resources out there that point to a dozen different solutions and none of them seem to work.

HTML on ASP.Net Page:

<div class="contentArea">
     <div class="block" id="button1" runat="server">
            Some Content Here
     </div>
     <div class="block" id="button2" runat="server">
            Some Content Here
     </div>
     <div class="block" id="button3" runat="server">
            Some Content Here
     </div>
</div>

C# Code Behind (examples I've tried):

System.Web.UI.HtmlControls.HtmlGenericControl div1 = (System.Web.UI.HtmlControls.HtmlGenericControl)this.FindControl("button1");
div1.Attributes["class"] = "classNameHere";

or

Control div1 = this.FindControl("button1");
div1.GetType();

When the code gets to the second line of each of the above examples, I get an error:

Object reference not set to an instance of an object.

If I try the following:

if (div1 != null)
{
    // Do Something;
}

Nothing ever happens because div1 is always set to null. Ironically, if I look at the Locals window and examine this, I can see the button# ids in the listing, so I know they are there, but the system is acting like it isn't finding the control.

My ultimate goal is to find the max id # of the button divs (looking at my html example, the max id would be 3 (button3). Maybe there is a better way to go about it, but either way, once I have my max id, I want to be able to touch each div and alter some css properties.

Although I could easily do all of this via jQuery, in this instance I need to do this in C#.

Any help is much appreciated. If you need more info, let me know.

UPDATE I created a new C# web project from scratch. After adding a masterpage (and not altering it) and adding a webform using masterpage, I only added one line to the webform under Content ID="Content2":

<div id="button1"></div>

From c# code behind I still run into the same exact issue as before.

FINAL UPDATE AND ANSWER I'm shocked no one (including myself) caught my mistake from the above update. I never put runat="server" when I created a new project from scratch under the div. Here is how I fixed my problem under my new project from scratch:

Add runat="server" to div:

<div id="button1" runat="server"></div>

Then I did a FindControl on the ContentPlaceHolder under the MasterPage:

ContentPlaceHolder myPlaceHolder = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");

Note: This is what the ContentPlaceHolder code looks like on the Site.Master page created by default:

<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

</asp:ContentPlaceHolder>

After finding this ContentPlaceHolder in code behind, I then searched within this placeholder for button1:

using System.Web.UI.HtmlControls;
HtmlControl myControl = (HtmlControl)myPlaceHolder.FindControl("button1");

Finally I check to see if myControl is null:

if (myControl != null)
{
    \\ Do Something
}

When I ran this code, it found the div I was looking for. Here is the complete code behind all put together:

using System.Web.UI.HtmlControls;

ContentPlaceHolder myPlaceHolder = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
HtmlControl myControl = (HtmlControl)myPlaceHolder.FindControl("button1");

if (myControl != null)
{
    // Do Something
}
Seismology answered 10/7, 2012 at 15:41 Comment(12)
FindControl works only for immediate descendant of current control (probably page). If the div is inside a panel typically, you will have to call findcontrol on the panel, or write a recursive method.Leake
Your divs are ID'd bodyDiv1, bodyDiv2, bodyDiv3, but you are searching for a control with ID button1? Is there something you haven't included in the example code?Shornick
@Steve - The divs are not within any type of control.Seismology
@Shornick - I apologize, I grabbed the wrong section of HTML from my file, I updated the above. The only difference in what I gave you compared to what I have is there are more divs then what I provided.Seismology
are the divs within the <form runat="server"> node ?Leake
Can you clarify how your HTML is being created? If that really is the HTML for the aspx page then I'm not sure why you cna't just accesson button1 directly without using findControl. I assume there is something more happening here though or it would be pointless... I assume that the divs are being generated dynamically on either the server or the client but it is very important to know which. If the client then you need to do somethign to tell the server about them or it won't know (and hence won't find them). So please include the code that is generating them if it exists...Punchinello
@Steve - Technically yes, <form runat="server"> is located on the MasterPage file. The ContentPlaceHolder that my html is within is a child of <form runat="server">Seismology
@Punchinello - Yes I could access them directly, essentially what I want to do is find what the max number is for any div element that has an id starting with "button". I didn't think I could programatically refer to an object by a string value (example: "button" + i) so I figured findControl was the next best thing.Seismology
your updated goal let think that you are dynamically generating divs.. isn't it ?Leake
@SteveB - Currently not needing to dynamically generate divs, but anytime I add a new div with button# in the future, I don't want to also have to update the C# code, hence why I want to programatically figure out how many divs exist on the page with button# as its ID.Seismology
@JasonH: Woudln't it be easier to always have the last button called the same thing (eg "buttonLast") and if you add new buttons you just make sure the last one stays called "buttonLast". I'm not sure what you are doing with this last button but getting it this way seems like a bit of a code smell to me...Punchinello
@Punchinello - Regardless of what my problem is, I need to be able to call a div on pageload and set css parameters to essentially hide/show a div. I know how to easily do this with javaScript, but the issue is that I want to pass in a variable via the URL, so that based off that variable a particular div container will show. I figured this should be a simple solution but its turned into being quite the opposite especially considering th activity on this post.Seismology
S
11

If your page is using a MasterPage, the div control will not be in the main collection of controls. That collection only contains the Content controls pointing to the ContentPlaceholder of your MasterPage.

There are three options:

  1. Use FindControl on the Content control: contentControl.FindControl("button1");
  2. Do a recursive FindControl until you find the control you need
  3. Normally, a declaration of your div control is added to your designer.cs codebehind, so you can directly access the control by its name: button1.Attributes["class"] = "classNameHere";

Update

I have created a MasterPage, added a Content Page to it, and added <div id="button1" runat="server">Some text</div> to the Content Page.

In the codebehind of my Content Page, I added this code:

protected void Page_Load(object sender, EventArgs e)
{
    var control = FindHtmlControlByIdInControl(this, "button1");

    if (control != null)
    {
        control.Attributes["class"] = "someCssClass";
    }
}

private HtmlControl FindHtmlControlByIdInControl(Control control, string id)
{
    foreach (Control childControl in control.Controls)
    {
        if (childControl.ID != null && childControl.ID.Equals(id, StringComparison.OrdinalIgnoreCase) && childControl is HtmlControl)
        {
            return (HtmlControl)childControl;
        }

        if (childControl.HasControls())
        {
            HtmlControl result = FindHtmlControlByIdInControl(childControl, id);
            if (result != null) return result;
        }
    }

    return null;
}

This works for me.

Supposing answered 10/7, 2012 at 16:23 Comment(4)
I've tried both 1 and 2 to no avail. #3 does not solve my issue, yes I can access them directly, but I need to be able to refer to the control name via a variable and I can't find anywhere how to do this other than a FindControl, which is ultimately failing me. So if you can tell me how I can essentially do: string button = "button" + i; and then call button.Attributes, then I can solve my problem in a different manor.Seismology
I have updated my answer with example code that works for me.Supposing
So when I created a new test site from scratch, I forgot to add runat=server to the div, so a lot of my testing yesterday went to waste. I tried your method and it worked, I also tried some other htings and it worked. Why it won't work yet on my normal project is another matter, but I can address that myself. Thanks!Seismology
Forgetting runat=server consume my hour too :DTurgid
P
1

If you add runat=server please add it at last of the div:

This will work

<div id="divBtn" class="mybuttonCass" runat="server">

However, this will not

<div runat="server" id="divBtn" class="mybuttonCass">

By doing that, you can modify any property from codebehind as:

divBtn.Style["display"] = "none";

This works even with masterpages. The div is not included in a masterpage.

Pirog answered 23/1, 2018 at 22:5 Comment(0)
M
0

You need to add a runat=server attribute to any control that you want to access in code behind. See this article for more help.

Accessing <div> from both javascript and code-behind

Milieu answered 10/7, 2012 at 15:44 Comment(1)
This is a very typical answer but is not the case here. As I stated when looking at the locals I can see the controls, and as Ruel stated, I have runat=server in my code already.Seismology
S
0

I cannot seem to be able to reproduce your problem, any chance your DIV's are within a template control such as UpdatePanel, Repeater, or Grid?

Silken answered 10/7, 2012 at 15:44 Comment(3)
The divs are within an <asp:Content> control from within a MasterPage setup. Other than that, they are not within any type of template control as you suggested.Seismology
what about yourContentControl.FindControl("yourdiv") ?Leake
Intellisense is not finding the Content control (and yes it has a unique ID and has runat=server).Seismology

© 2022 - 2024 — McMap. All rights reserved.