如何更改此DropDownList声明,以便有条件地启用/禁用disabled属性?
<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled="disabled"} %>
非工作示例:
<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled=Model.CanEdit?"false":"disabled"} %>
P.S。在整个语句中添加if条件不是理想的方法:)
编辑:基于另一个问题的this扩展方法,我想出了以下扩展程序:
public static IDictionary<string, object> Disabled (this object obj, bool disabled)
{
return disabled ? obj.AddProperty ("disabled", "disabled") : obj.ToDictionary ();
}
然后可以用作
<%= Html.DropDownList("Quantity", new SelectList(...), new{id="quantity"}.Disabled(Model.CanEdit) %>
答案 0 :(得分:27)
无需添加辅助方法,只需使用
即可<%= Html.DropDownList("Quantity", new SelectList(...), IsEditable == true ? new { @disabled = "disabled" } as object : new {} as object %>
如果要删除as object
条目,这将无效,因为默认情况下new {}
是在运行时编译的动态对象,因此两个可能的对象必须具有相同的属性。但是Html属性参数实际上只是一个对象,所以这些动态可以作为对象进行转换。
此解决方案甚至允许您使用多个HTML属性,其中一个是可选的而另一个不是,即class='whatever'
不是可选的,disabled
是因此您将class='whatever'
放在两个对象中,但只有第一个可选的。 Dimitrov的答案不支持除禁用之外的任何自定义属性。
答案 1 :(得分:19)
请不要写意大利面条代码。 Html助手就是为了这个目的:
public static MvcHtmlString DropDownList(this HtmlHelper html, string name, SelectList values, bool canEdit)
{
if (canEdit)
{
return html.DropDownList(name, values);
}
return html.DropDownList(name, values, new { disabled = "disabled" });
}
然后:
<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit) %>
或许你可以提出更好的东西(如果模型包含选项):
<%= Html.DropDownList("Quantity", Model) %>
您还将获得更多单元可测试代码的奖励。
答案 2 :(得分:9)
一个选项是创建一个Html.DropDownList的自定义版本,它接受一个额外的参数并做你想要的...但是你必须为每种类型的帮助器创建一个新的 - TextBoxFor,TextAreaFor,CheckBoxFor等......你仍然需要弄清楚如何使它的内脏发挥作用。
相反,我选择创建一个Html Helper来替换普通的匿名HtmlAttributes对象,从那时起它将与所有使用HtmlAttributes而没有任何特殊工作的Helper兼容。此解决方案还允许您传递其他属性,如类,名称或任何您想要的属性。它不会将您锁定为仅禁用。
我创建了以下Helper - 它需要一个布尔值和一个匿名对象。如果disabled为true,则将disabled属性添加到匿名对象(实际上是Dictionary),其值为“disabled”,否则根本不添加该属性。
public static RouteValueDictionary ConditionalDisable(
bool disabled,
object htmlAttributes = null)
{
var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (disabled)
dictionary.Add("disabled", "disabled");
return dictionary;
}
它的一个例子:
@Html.TextBoxFor(m => m.SomeProperty,
HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))
这种方法的一个巨大优势是它几乎适用于所有MVC HtmlHelper,因为它们都具有接受RouteValueDictionary而不是匿名对象的Overload。
<强>注意事项强>:
HtmlHelper.AnonymousObjectToHtmlAttributes()使用一些奇特的代码忍者工作来完成工作。我不完全确定它的性能如何......但它足以满足我的需求。您的里程可能会有所不同。
我并不特别喜欢它的名字 - 但我无法想出更好的东西。重命名很容易。
我也不喜欢使用语法 - 但是我再也找不到更好的了。改变应该不难。 object
上的扩展方法是一个想法...你最终会得到new { @class = "someClass" }.ConditionalDisable(true)
但是如果你只想要禁用属性并且没有任何额外的东西可以添加,那么你最终会得到一些粗略的东西比如new {}.ConditionalDisable(true);
,你最终会得到一个显示所有对象的扩展方法......这可能是不可取的。
答案 3 :(得分:2)
@bool IsEditable=true;
@if (IsEditable)
{
Html.DropDownListFor(m => m, selectList);
}
else
{
Html.DropDownListFor(m => m, selectList, new { disabled = "disabled" })
}
答案 4 :(得分:0)
强类型的verison:
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList,
string optionText, bool canEdit)
{
if (canEdit)
{
return html.DropDownListFor(expression, selectList, optionText);
}
return html.DropDownListFor(expression, selectList, optionText, new { disabled = "disabled" });
}
答案 5 :(得分:0)
为了完整性,这里有一个保留所有参数并将选择值发布到服务器:
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool enabled)
{
if (enabled)
{
return SelectExtensions.DropDownListFor<TModel, TProperty>(html, expression, selectList, htmlAttributes);
}
var htmlAttributesAsDict = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
htmlAttributesAsDict.Add("disabled", "disabled");
string selectClientId = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression));
htmlAttributesAsDict.Add("id", selectClientId + "_disabled");
var hiddenFieldMarkup = html.HiddenFor<TModel, TProperty>(expression);
var selectMarkup = SelectExtensions.DropDownListFor<TModel, TProperty>(html, expression, selectList, htmlAttributesAsDict);
return MvcHtmlString.Create(selectMarkup.ToString() + Environment.NewLine + hiddenFieldMarkup.ToString());
}
用法示例,如果列表中只有一个项目,则禁用下拉列表,仍然会将一个值发布到具有正确客户端ID的服务器:
@Html.DropDownListFor(m => m.SomeValue, Model.SomeList, new { @class = "some-class" }, Model.SomeList > 1)
答案 6 :(得分:0)
您可以这样做:
var dropDownEditDisable = new { disabled = "disabled" };
var dropDownEditEnable = new { };
object enableOrDisable = Model.CanEdit ?
(object)dropDownEditEnable : (object)dropDownEditDisable;
@Html.DropDownList("Quantity", new SelectList(...), enableOrDisable)
Html.DropDownListFor()可以很长,因此无需重复。
答案 7 :(得分:-2)
我不知道ASP.NET是否提供了更简洁的特殊情况方法,但可能你可以做到:
<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit? new{@class="quantity"} : new{@class="quantity", @disabled:"disabled"}) %>