public static void CssAddClass(this Control control, string className)
{
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;
}
}
public static void CssRemoveClass
(this Control control, string className, bool mayNotExist)
{
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;
}
}
Refactorings
No refactoring yet !
Dizzle
May 2, 2009, May 02, 2009 23:14, permalink
I don't understand what you're trying to accomplish. Are you attempting to code infinity around control.CssClass = "class-name" ?
Ants
May 3, 2009, May 03, 2009 03:12, permalink
Try applying some DRY principles... Now if somebody could refactor the Get/SetCssClass() methods below to be even DRY-er.
static string GetCssClass(Control control)
{
if (control == null)
throw new ArgumentNullException("control");
WebControl web = control as WebControl;
HtmlControl html = control as HtmlControl;
if (web != null)
return web.CssClass;
else if (html != null)
return html.Attributes["class"];
throw new ArgumentException("Must be WebControl or HtmlControl.", "control");
}
static void SetCssClass(Control control, string classAttributeValue)
{
if (control == null)
throw new ArgumentNullException("control");
WebControl web = control as WebControl;
HtmlControl html = control as HtmlControl;
if (web != null)
web.CssClass = classAttributeValue;
else if (html != null)
html.Attributes["class"] = classAttributeValue;
throw new ArgumentException("Must be WebControl or HtmlControl.", "control");
}
static void SetCssClass(Control control, List<string> classNameList)
{
SetCssClass(control, String.Join(" ", classNameList.ToArray()));
}
static List<string> GetClassNames(string classAttributeValue)
{
if (String.IsNullOrEmpty(classAttributeValue))
return new List<string>();
return new List<string>(classAttributeValue.Split(new[] { ' ' },
StringSplitOptions.RemoveEmptyEntries));
}
static void ValidateClassNameArg(string className)
{
if (className == null)
throw new ArgumentNullException("className");
else if (className == String.Empty)
throw new ArgumentException("className cannot be empty", "className");
}
public static void CssAddClass(this Control control, string className)
{
ValidateClassNameArg(className);
var classNameList = GetClassNames(GetCssClass(control));
if (!classNameList.Contains(className))
{
classNameList.Add(className);
SetCssClass(control, classNameList);
}
}
public static void CssRemoveClass
(this Control control, string className, bool mayNotExist)
{
ValidateClassNameArg(className);
var classNameList = GetClassNames(GetCssClass(control));
if (!mayNotExist && classNameList.Count == 0)
throw new ArgumentException("Does not have any CSS classes defined.", className);
if (classNameList.Remove(className))
SetCssClass(control, classNameList);
}
Ants
May 4, 2009, May 04, 2009 07:32, permalink
In an attempt to make things DRY-er, I came up with this second refactoring to apply a strategy pattern to try to encapsulate the knowledge of how to get/set the appropriate control properties.
static class CssClassExtensions
{
struct GetSet
{
public Func<object, string> Get;
public Action<object, string> Set;
}
static Dictionary<Type, GetSet> s_getsets = new Dictionary<Type, GetSet>();
static void Register<T>(Func<T, string> getter,
Action<T, string> setter)
{
s_getsets.Add(typeof(T),
new GetSet()
{
Get = o => getter((T) o),
Set = (o, s) => setter((T) o, s)
});
}
static CssClassExtensions()
{
Register<WebControl>(web => web.CssClass,
(web, s) => web.CssClass = s);
Register<HtmlControl>(html => html.Attributes["class"],
(html, s) => html.Attributes["class"] = s);
}
static GetSet FindGetSet(Control control)
{
if (control == null)
throw new ArgumentNullException("control");
foreach (Type type in s_getsets.Keys)
{
if (type.IsInstanceOfType(control))
return s_getsets[type];
}
throw new ArgumentException(String.Format("No registered CSS class accessor for {0}.",
control.GetType()),
"control");
}
static string GetCssClass(Control control)
{
return FindGetSet(control).Get(control);
}
static void SetCssClass(Control control, string classAttributeValue)
{
FindGetSet(control).Set(control, classAttributeValue);
}
static void SetCssClass(Control control, List<string> classNameList)
{
SetCssClass(control, String.Join(" ", classNameList.ToArray()));
}
static List<string> GetClassNames(string classAttributeValue)
{
if (String.IsNullOrEmpty(classAttributeValue))
return new List<string>();
return new List<string>(classAttributeValue.Split(new[] { ' ' },
StringSplitOptions.RemoveEmptyEntries));
}
static void ValidateClassNameArg(string className)
{
if (className == null)
throw new ArgumentNullException("className");
else if (className == String.Empty)
throw new ArgumentException("className cannot be empty", "className");
}
public static void CssAddClass(this Control control, string className)
{
ValidateClassNameArg(className);
var classNameList = GetClassNames(GetCssClass(control));
if (!classNameList.Contains(className))
{
classNameList.Add(className);
SetCssClass(control, classNameList);
}
}
public static void CssRemoveClass
(this Control control, string className, bool mayNotExist)
{
ValidateClassNameArg(className);
var classNameList = GetClassNames(GetCssClass(control));
if (!mayNotExist && classNameList.Count == 0)
throw new ArgumentException("Does not have any CSS classes defined.", className);
if (classNameList.Remove(className))
SetCssClass(control, classNameList);
}
}
Have at it.