Add a CSS Class in ASP.NET
Posted April 17, 2009 by Chris | Filed under ASP.NET, CSS
Adding or removing a CSS class to an element in jQuery is easy enough:
$("#elementId").addClass("className"); $("#elementId").removeClass("className");
But how can this be done in ASP.NET? Shouldn't it be as easy? Should? Yes. Is? Almost. For the quick solution and code, jump to the end of this post. (That's what this is really here for anyway—to host the code for future reference.) For the gratuitously verbose explanation, continue.
ASP.NET Control Types
The value of an HTML tag's "class" attribute can contain one or more class names, separated by a space. For example:
<div id="myDiv" class="foo bar" />In ASP.NET, if an HTML tag has a "runat" attribute with "server" as its value, ASP.NET types it as an object derived from System.Web.UI.HtmlControl:
<!-- (myDiv is System.Web.UI.HtmlControl) == true --> <div runat="server" id="myDiv" class="foo bar" />
When an object is an HtmlControl, the "class" attribute's value is the control's
string classAttributeValue = this.myDiv.Attribute["class"]; //classAttributeValue == "foo bar"
If the tag is an
<!-- (myTextBox is WebControl) == true --> <asp:TextBox runat="server" id="myTextBox" class="foo bar" />
When an object is a WebControl, the tag's "class" attribute's value is the object's
string classAttributeValue = this.myTextBox.CssClass; // classAttributeValue == "foo bar"
Adding/Removing a CSS Class
The naive approach to add a class to a control, which I saw, would be:
void CssAddClass(WebControl ctl, string className) { ctl.CssClass += " " + className; } void CssAddClass(HtmlControl ctl, string className) { ctl.Attributes["class"] += " " + className; }
Removing the classes would then be accomplished using similar methods:
void CssRemoveClass(WebControl ctl, string className) { ctl.CssClass = ctl.CssClass.Replace(" " + className, string.Empty); } void CssRemoveClass(HtmlControl ctl, string className) { ctl.Attributes["class"] = ctl.Attributes["class"].Replace(" " + className, string.Empty); }
Nice and simple—and fallible. If the control doesn't have any "class" attribute defined, the control's member for the class value is null:
<!-- Given these tags... --> <div id="myDiv" runat="server" /> <asp:TextBox id="myTextBox" runat="server" />
// ...and this codebehind, this.myDiv.Attributes["class"] += " " + className; this.myTextBox.CssClass += " " + className; // ...you get a NullReferenceException from both
Null reference checking is OOP 101. If a class member can return a reference type, it can return
Or, what if the CSS class is already defined in the attribute? By using
Program defensively. The class attribute should be identified as having a value or not before trying to change it, and checked for the pre-existence of the class to add.
Extension Goodies
I've implemented the add/remove functionality as extension methods, and they use LINQ, so you'll need .NET 3.5. The extension methods are on ASP.NET
A quick superfluous example follows. Given an ASPX with this:
<div id="ViewContainer" runat="server" /> <asp:Label id="UserName" runat="server" />
Here's the Page's codebehind to add a couple classes:
this.ViewContainer.CssAddClass("container"); this.UserName.CssAddClass("hilight");
To remove a class, use CssRemoveClass(). Be careful though: if it isn't defined, an ArgumentException is thrown. If you're not sure if that class is defined or not and don't want to deal with the exception, pass
// Sure ViewContainer has class="container" this.ViewContainer.CssRemoveClass("container"); // Not sure UserName has class="error" this.UserName.CssRemoveClass("error", true);
The methods begin with "Css" instead of "Add" or "Remove" so they're quicker to find in Intellisense. You may notice the redundancy with type-checking and getting/setting the CSS class name attribute, but I don't think it warrants augmenting the code.
Remember to include the
using System; using System.Linq; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; /// <summary> /// Extension methods for System.Web.UI.Control. /// </summary> public static class ControlExtension { /// <summary> /// Add a CSS class to a WebControl or HtmlControl. /// </summary> /// <param name="control"> /// The WebControl or HtmlControl to add the CSS class to. /// </param> /// <param name="className"> /// The name of the CSS class to add. /// </param> /// <exception cref="System.ArgumentNullException"> /// control is null or className is null. /// </exception> /// <exception cref="System.ArgumentException"> /// The control is not a WebControl or HtmlControl. /// </exception> public static void CssAddClass(this Control control, string className) { // by Chris O'Brien, prettycode.org if (control == null) { throw new ArgumentNullException("control"); } if (className == null) { throw new ArgumentNullException("className"); } string classAttributeValue; if (control is WebControl) { classAttributeValue = (control as WebControl).CssClass; } else if (control is HtmlControl) { classAttributeValue = (control as HtmlControl).Attributes["class"]; } else { throw new ArgumentException ("Must be WebControl or HtmlControl.", "control"); } if (string.IsNullOrEmpty(classAttributeValue)) { classAttributeValue = className; } else { var classNameList = classAttributeValue.Split (new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (classNameList.Contains(className)) { return; } classAttributeValue = string.Concat (classNameList.Select(name => name + " ").ToArray()) + className; } if (control is WebControl) { (control as WebControl).CssClass = classAttributeValue; } else if (control is HtmlControl) { (control as HtmlControl).Attributes["class"] = classAttributeValue; } } /// <summary> /// Remove a CSS class from a WebControl or HtmlControl. /// </summary> /// <param name="control"> /// The WebControl or HtmlControl to remove the CSS class from. /// </param> /// <param name="className"> /// The name of the CSS class to remove. /// </param> public static void CssRemoveClass(this Control control, string className) { control.CssRemoveClass(className, false); } /// <summary> /// Remove a CSS class from a WebControl or HtmlControl. /// </summary> /// <param name="control"> /// The WebControl or HtmlControl to remove the CSS class from. /// </param> /// <param name="className"> /// The name of the CSS class to remove. /// </param> /// <param name="mayNotExist"> /// Specify true to not throw an ArgumentException if the control doesn't /// have the CSS class to remove. /// </param> /// <exception cref="System.ArgumentNullException"> /// control is null or className is null. /// </exception> /// <exception cref="System.ArgumentException"> /// The control is not a WebControl or HtmlControl, or when mayNotExist is false, /// the CSS class cannot be removed because the control does not define it. /// </exception> public static void CssRemoveClass (this Control control, string className, bool mayNotExist) { // by Chris O'Brien, prettycode.org if (control == null) { throw new ArgumentNullException("control"); } if (className == null) { throw new ArgumentNullException("className"); } string classAttributeValue; if (control is WebControl) { classAttributeValue = (control as WebControl).CssClass; } else if (control is HtmlControl) { classAttributeValue = (control as HtmlControl).Attributes["class"]; } else { throw new ArgumentException ("Must be WebControl or HtmlControl.", "control"); } bool isNullOrEmpty = string.IsNullOrEmpty(classAttributeValue); if (!mayNotExist && isNullOrEmpty) { throw new ArgumentException ("Does not have any CSS classes defined.", className); } else if (isNullOrEmpty) { classAttributeValue = string.Empty; } var classNames = from name in classAttributeValue.Split (new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) where name != className select name + " "; classAttributeValue = string.Concat(classNames.ToArray()).TrimEnd(); if (control is WebControl) { (control as WebControl).CssClass = classAttributeValue; } else if (control is HtmlControl) { (control as HtmlControl).Attributes["class"] = classAttributeValue; } } }