One option is creating a custom version of Html.DropDownList that takes an extra parameter and does what you want... but then you would have to make a new one for every type of helper - TextBoxFor, TextAreaFor, CheckBoxFor, etc... and you still have to figure out how to make the guts of it work.
I opted, instead, to create an Html Helper to replace the normal anonymous HtmlAttributes object since then it would be compatible with all of the Helpers that use HtmlAttributes without any special work. This solution also lets you pass through additional Attributes like Class, Name, or whatever you want. It doesn't lock you down to only disabled.
I created the following Helper - it takes a boolean and an anonymous object. If disabled is true, it adds the disabled attribute to the anonymous object (which is actually a Dictionary) with the value "disabled", otherwise it doesn't add the property at all.
public static RouteValueDictionary ConditionalDisable(
bool disabled,
object htmlAttributes = null)
{
var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (disabled)
dictionary.Add("disabled", "disabled");
return dictionary;
}
An example of it in action:
@Html.TextBoxFor(m => m.SomeProperty,
HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))
One huge advantage to this approach for me was that it works with virtually all of the MVC HtmlHelpers since they all have Overloads that accept a RouteValueDictionary instead of an anonymous object.
Caveats:
HtmlHelper.AnonymousObjectToHtmlAttributes() uses some fancy code ninja work to get things done. I'm not entirely sure how performant it is... but it's been sufficient for what I use it for. Your mileage may vary.
I don't especially like the name of it - but I couldn't come up with anything better. Renaming is easy.
I also don't love the usage syntax - but again I couldn't come up with anything better. It shouldn't be difficult to change. An extension method on object
is one idea... you'd end up with new { @class = "someClass" }.ConditionalDisable(true)
but then if you only want the disable attribute and don't have anything additional to add you end up with something gross like new {}.ConditionalDisable(true);
and you also end up with an extension method that shows up for all objects... which is probably not desirable.