有条件地禁用Html.DropDownList

Tod*_*ith 18 asp.net-mvc

如何更改此DropDownList声明,以便有条件地启用/禁用disabled属性?

<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled="disabled"} %>
Run Code Online (Sandbox Code Playgroud)

非工作的例子:

<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled=Model.CanEdit?"false":"disabled"} %>
Run Code Online (Sandbox Code Playgroud)

ps在整个语句周围添加if条件不是一个理想的方法:)

编辑:根据这个扩展方法从另一个问题我提出了以下扩展:

public static IDictionary<string, object> Disabled (this object obj, bool disabled)
{
  return disabled ? obj.AddProperty ("disabled", "disabled") : obj.ToDictionary ();
}
Run Code Online (Sandbox Code Playgroud)

然后可以用作

<%= Html.DropDownList("Quantity", new SelectList(...), new{id="quantity"}.Disabled(Model.CanEdit) %>
Run Code Online (Sandbox Code Playgroud)

era*_*mus 28

无需添加辅助方法,您只需使用即可

<%= Html.DropDownList("Quantity", new SelectList(...), IsEditable == true ? new { @disabled = "disabled" } as object : new {} as object %>
Run Code Online (Sandbox Code Playgroud)

如果要删除这些as object条目,则无效,因为默认情况下new {}是在运行时编译的动态对象,因此两个可能的对象必须具有相同的属性.但是Html属性参数实际上只是一个对象,所以这些动态可以作为对象来转换.

这个解决方案甚至允许你使用多个HTML属性,其中一个是可选的而另一个不是,即class='whatever'不是可选的,disabled所以你放入class='whatever'两个对象,但只有第一个可选的.Dimitrov的答案不支持除禁用之外的任何自定义属性.

  • +1这应该被标记为最佳答案 (6认同)

Dar*_*rov 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" });
}
Run Code Online (Sandbox Code Playgroud)

然后:

<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit) %>
Run Code Online (Sandbox Code Playgroud)

或者也许你可以提出更好的东西(如果模型包含选项):

<%= Html.DropDownList("Quantity", Model) %>
Run Code Online (Sandbox Code Playgroud)

您还将获得更多单元可测试代码的奖励.

  • 由于WebForms引擎的性质,您无法对视图进行单元测试.你可以测试扩展方法.这样,您的视图将不再包含值得单元测试的条件逻辑.通过测试扩展方法,您可以确保使用它的所有视图都能按预期运行,并具有完全标记,具体取决于模型上的"CanEdit"属性. (2认同)

Mir*_*Mir 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;
}
Run Code Online (Sandbox Code Playgroud)


它的一个例子:

@Html.TextBoxFor(m => m.SomeProperty,    
   HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))
Run Code Online (Sandbox Code Playgroud)


这种方法的一个巨大优势在于它几乎适用于所有MVC HtmlHelper,因为它们都具有接受RouteValueDictionary而不是匿名对象的Overload.

注意事项:
HtmlHelper.AnonymousObjectToHtmlAttributes()使用一些奇特的代码忍者工作来完成工作.我不完全确定它的性能如何......但它足以满足我的需求.你的旅费可能会改变.

我不是特别喜欢它的名字 - 但我无法想出更好的东西.重命名很容易.

我也不喜欢使用语法 - 但我又无法想出更好的东西.改变应该不难.一个扩展方法object是一个想法......你最终会得到new { @class = "someClass" }.ConditionalDisable(true)但是如果你只想要禁用属性并且没有任何额外的东西来添加你最终会得到一些粗略的东西new {}.ConditionalDisable(true);,你最终也会得到一个扩展方法显示所有对象...这可能是不可取的.


小智 6

@bool IsEditable=true;

@if (IsEditable)
{
    Html.DropDownListFor(m => m, selectList);
}
else
{
    Html.DropDownListFor(m => m, selectList, new { disabled = "disabled" })
}
Run Code Online (Sandbox Code Playgroud)