asp.net-mvc 有条件地禁用 Html.DropDownList

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2089468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:04:26  来源:igfitidea点击:

Conditionally disable Html.DropDownList

asp.net-mvc

提问by Todd Smith

How can I change this DropDownList declaration so that the disabled attribute is enable/disabled conditionally?

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

<%= Html.DropDownList("Quantity", new SelectList(...), new{@disabled="disabled"} %>

non-working example:

非工作示例:

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

p.s. adding an if condition around the entire statement is not a desired approach :)

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

EDIT:based on thisextension method from another question I came up with the following extension:

编辑:基于另一个问题的这个扩展方法,我想出了以下扩展:

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

which can then be used as

然后可以用作

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

回答by erasmus

There is no need to add helper methods, you can just use

不需要添加辅助方法,你可以直接使用

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

If you were to remove the as objectentries this wouldn't work because by default new {}is a dynamic object compiled at runtime, therefore the two possible objects must have the same properties. But the Html attributes parameter is actually just an object, so these dynamics can be cast as objects to get around this.

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

This solution even allows you to use multiple HTML attributes where one is optional and another is not, i.e class='whatever'is not optional but disabledis so you put class='whatever'in both the objects, but the optional one only in the first. Dimitrov's answer does not support any custom attributes other than disabled.

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

回答by Darin Dimitrov

Please don't write spaghetti code. Html helpers are there for this purpose:

请不要写意大利面条式的代码。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" });
}

And then:

进而:

<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit) %>

Or maybe you could come up with something even better (if the model contains the options):

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

<%= Html.DropDownList("Quantity", Model) %>

You will also get the bonus of having more unit testable code.

您还将获得更多单元可测试代码的好处。

回答by Mir

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.

一种选择是创建一个自定义版本的 Html.DropDownList,它需要一个额外的参数并执行您想要的操作……但是您必须为每种类型的助手创建一个新版本 - TextBoxFor、TextAreaFor、CheckBoxFor 等……你仍然需要弄清楚如何让它发挥作用。

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.

相反,我选择创建一个 Html Helper 来替换普通的匿名 HtmlAttributes 对象,从那时起它将与所有使用 HtmlAttributes 的 Helper 兼容,而无需任何特殊工作。此解决方案还允许您传递其他属性,如类、名称或任何您想要的。它不会将您锁定为仅禁用。

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.

我创建了以下 Helper - 它需要一个布尔值和一个匿名对象。如果 disabled 为 true,则将 disabled 属性添加到值为“disabled”的匿名对象(实际上是一个 Dictionary),否则它根本不添加该属性。

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.

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

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.

注意事项
HtmlHelper.AnonymousObjectToHtmlAttributes() 使用一些花哨的代码忍者工作来完成任务。我不完全确定它的性能如何......但是对于我使用它的目的来说已经足够了。你的旅费可能会改变。

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 objectis 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.

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

回答by SumanReddy

@bool IsEditable=true;

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

回答by Antonio Bakula

For completeness here is one that preservers all parameters and it would post select value to the server:

为了完整起见,这里保留了所有参数,并将选择值发布到服务器:

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());
}

Usage example, disable drop down if there is only one item in list, that one value is still posted to server with correct client id:

用法示例,如果列表中只有一项,则禁用下拉列表,该值仍会以正确的客户端 ID 发布到服务器:

@Html.DropDownListFor(m => m.SomeValue, Model.SomeList, new { @class = "some-class" }, Model.SomeList > 1)

回答by proggrock

Strongly typed 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" });
    }

回答by bobince

I don't know if ASP.NET offers a more succinct special-case approach, but presumably you could do:

我不知道 ASP.NET 是否提供了更简洁的特殊情况方法,但大概你可以这样做:

<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit? new{@class="quantity"} : new{@class="quantity", @disabled:"disabled"}) %>