2

So I have a user control that displays links and I want to change the color of the link that is currently active. This is the code inside my ListView of my usercontrol ascx file.

<asp:ListView ID="sidebarListView" runat="server" DataKeyNames="Id" DataSourceID="SqlDataSourceSidebar" OnItemCommand="sidebarListView_ItemCommand">
<ItemTemplate>
  <div id="sidebarItemID" class="sidebarItem" runat="server">
     <div>
        <asp:LinkButton ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' CommandName="Select" CommandArgument='<%# Eval("Id") %>' />
     </div>
  </div>
</ItemTemplate>
....

I need to change the sidebarItemID class when the linkbutton is clicked. My default.aspx code behind looks like this:

private void SideBar1_ItemCommand ( object sender , EventArgs e ) {
  Int32 facId = Sidebar1.FacultyId;
  SqlDataSource1.SelectCommand = "SELECT [Id], [Name], [Faculty_Id], [User_Id], [Author], [Picture], [Location] FROM [Books] WHERE [Faculty_Id]=" + facId + " ORDER BY [DateAdded] DESC";
  HtmlGenericControl htmlDivControl = (HtmlGenericControl) FindControlRecursive( Sidebar1 , "sidebarItemID" );
  htmlDivControl.Attributes.Add("class", "sidebarItemActive");
  string newClass = htmlDivControl.Attributes["class"];
  //Response.Write( String.Format( "<script>alert('{0}');</script>" , newClass ) );
}

This correctly changes the sqlDataSource based on the ID of the link clicked in the user control. However the class doesn't change.

If I uncomment the Response.Write(...) section it correctly gives an alert that says "sidebarItemActive" so it correctly finds the control from my page and assigns its class attribute as "sidebarItemActive" but nothing changes on the page if I view the page source in the browser it says the class is still "sidebarItem". What is going on here that the change does not come into effect?

7
  • Perhaps the attribute already exists and adding it doesn't take effect as you wish? Try htmlDivControl.Attributes["class"] = "sidebarItemActive"; EDIT: That actually probably won't work. Check that the ID of the div on the page is actually sidebarItemID, because controls can append their control name to the id. Commented Jun 28, 2012 at 17:07
  • I tried it, same thing. Besides as far as i know Add acts the same as Put, so it replaces the value if it is already set. Commented Jun 28, 2012 at 17:12
  • Hmm. On the page, the ID is indeed not "SidebarItemID" but rather "sidebar_Sidebar1_sidebarListView_sidebarItemID_0" etc. But How does the findcontrol method actually find the element then? Also if i set the user controls ClientIDMode as static it still doesnt work, but all the items in the ListView have the same ID, but the class still does not change Commented Jun 28, 2012 at 17:20
  • I think this has to do with the page lifecycle. Postbacks are handled before renders, and since you're using a template for your div, the actual set of sidebar divs is created after your code is handled. Try doing this on Render of the control . If this works as I hope it should, I'll submit it as an answer Commented Jun 28, 2012 at 17:37
  • Hmm, I'm not sure that I understand. Basically, I can't do it on the render of the control, because when the control is rendered I don't need the class to change. I need it changed when the user clicks a link in the control. Did I understand you correctly? And thanks for helping Commented Jun 28, 2012 at 17:54

2 Answers 2

1

The actual <div>s on your page are generated during the Render state of the ASP.NET Page Life Cycle. This happens after the Control event handling stage, thus any changes you make to the HTML during your handler function are effectively undone during Render, as the control's HTML is regenerated from the template. To have the control change its internal HTML in this case, you may put your update code in an overridden Render function for your control. The MSDN has an example of how to write the render function.

Sign up to request clarification or add additional context in comments.

Comments

1

So I solved the problem by defining the ListViews ItemDataBound event handler and assigning the css class in there. The problem previously was, that since my controls were inside updatePanels the ItemDataBound event was not firing. I had to manually call "DataBind()" inside the click method.

Inside my default.aspx

// Exposed click event, updates RecentBooks control sqlDataSource.
private void SidebarItems1_Clicked ( object sender , EventArgs e ) {
  RecentBooks1.updateDataSource( SidebarItems1.FacultyId.ToString() );
  SidebarItems1.DataBind();

}

Inside my user control.ascx

protected void sidebarListView_ItemDataBound ( object sender , ListViewItemEventArgs e ) {
  LinkButton button = e.Item.FindControl( "NameLabel" ) as LinkButton;
  if (FacultyName != null && button != null) {
     if ( button.Text == FacultyName ) {
        button.CssClass = "sidebarItemActive";
     }
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.