根据Html.TextBoxFor的条件设置禁用属性

Gho*_*ngi 74 asp.net-mvc html-helper razor asp.net-mvc-3

我想根据下面的asp.net MVC中的Html.TextBoxFor条件设置disable属性

@Html.TextBoxFor(model => model.ExpireDate, new { style = "width: 70px;", maxlength = "10", id = "expire-date" disabled = (Model.ExpireDate == null ? "disable" : "") })
Run Code Online (Sandbox Code Playgroud)

该助手有两个输出禁用="禁用"或禁用="".两个主题都使文本框禁用.

如果Model.ExpireDate == null,我想禁用文本框,否则我想启用它

Dar*_*rov 81

有效的方法是:

disabled="disabled"
Run Code Online (Sandbox Code Playgroud)

浏览器也可以接受, disabled=""但我建议你采用第一种方法.

现在我要建议你编写一个自定义HTML帮助程序,以便将这个禁用功能封装到一个可重用的代码段中:

using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Routing;

public static class HtmlExtensions
{
    public static IHtmlString MyTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        object htmlAttributes, 
        bool disabled
    )
    {
        var attributes = new RouteValueDictionary(htmlAttributes);
        if (disabled)
        {
            attributes["disabled"] = "disabled";
        }
        return htmlHelper.TextBoxFor(expression, attributes);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用:

@Html.MyTextBoxFor(
    model => model.ExpireDate, 
    new { 
        style = "width: 70px;", 
        maxlength = "10", 
        id = "expire-date" 
    }, 
    Model.ExpireDate == null
)
Run Code Online (Sandbox Code Playgroud)

你可以为这个助手带来更多智慧:

public static class HtmlExtensions
{
    public static IHtmlString MyTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        object htmlAttributes
    )
    {
        var attributes = new RouteValueDictionary(htmlAttributes);
        var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        if (metaData.Model == null)
        {
            attributes["disabled"] = "disabled";
        }
        return htmlHelper.TextBoxFor(expression, attributes);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在你不再需要指定禁用的条件:

@Html.MyTextBoxFor(
    model => model.ExpireDate, 
    new { 
        style = "width: 70px;", 
        maxlength = "10", 
        id = "expire-date" 
    }
)
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案很棒 - 就目前而言......但是找到一个干净的解决方案并不需要在我们使用的可能具有禁用属性的每个HtmlHelper周围放置一个包装器(TextBoxFor,TextAreaFor,CheckBoxFor等等)会很不错. .)理想情况下,与现有工作内联的工作.我已经构建了一个基本上只包装匿名对象并返回RouteValueDictionary的解决方案 - 但它感觉不是特别干净. (4认同)
  • "disabled","disabled =''"和"disabled ='disabled'"在html中同样有效,并且误导(和错误)说较短的那些可能只被*不同的浏览器*接受*.参看 http://dev.w3.org/html5/markup/syntax.html#syntax-attr-empty (3认同)

Shi*_*mmy 43

实际上,内部行为是将匿名对象转换为字典.所以我在这些场景中所做的就是找一本字典:

@{
  var htmlAttributes = new Dictionary<string, object>
  {
    { "class" , "form-control"},
    { "placeholder", "Why?" }        
  };
  if (Model.IsDisabled)
  {
    htmlAttributes.Add("disabled", "disabled");
  }
}
@Html.EditorFor(m => m.Description, new { htmlAttributes = htmlAttributes })
Run Code Online (Sandbox Code Playgroud)

或者,斯蒂芬在这里评论道:

@Html.EditorFor(m => m.Description,
    Model.IsDisabled ? (object)new { disabled = "disabled" } : (object)new { })
Run Code Online (Sandbox Code Playgroud)


use*_*646 23

我喜欢达林方法.但快速解决这个问题的方法,

Html.TextBox("Expiry", null, new { style = "width: 70px;", maxlength = "10", id = "expire-date", disabled = "disabled" }).ToString().Replace("disabled=\"disabled\"", (1 == 2 ? "" : "disabled=\"disabled\""))
Run Code Online (Sandbox Code Playgroud)


Mur*_*zaB 13

我使用一些扩展方法实现了它

private const string endFieldPattern = "^(.*?)>";

    public static MvcHtmlString IsDisabled(this MvcHtmlString htmlString, bool disabled)
    {
        string rawString = htmlString.ToString();
        if (disabled)
        {
            rawString = Regex.Replace(rawString, endFieldPattern, "$1 disabled=\"disabled\">");
        }

        return new MvcHtmlString(rawString);
    }

    public static MvcHtmlString IsReadonly(this MvcHtmlString htmlString, bool @readonly)
    {
        string rawString = htmlString.ToString();
        if (@readonly)
        {
            rawString = Regex.Replace(rawString, endFieldPattern, "$1 readonly=\"readonly\">");
        }

        return new MvcHtmlString(rawString);
    }
Run Code Online (Sandbox Code Playgroud)

然后....

@Html.TextBoxFor(model => model.Name, new { @class= "someclass"}).IsDisabled(Model.ExpireDate == null)
Run Code Online (Sandbox Code Playgroud)


小智 11

我使用的一个简单方法是条件渲染:

@(Model.ExpireDate == null ? 
  @Html.TextBoxFor(m => m.ExpireDate, new { @disabled = "disabled" }) : 
  @Html.TextBoxFor(m => m.ExpireDate)
)
Run Code Online (Sandbox Code Playgroud)


And*_*hau 11

如果您不使用html助手,您可以使用简单的三元表达式,如下所示:

<input name="Field"
       value="@Model.Field" tabindex="0"
       @(Model.IsDisabledField ? "disabled=\"disabled\"" : "")>
Run Code Online (Sandbox Code Playgroud)


koo*_*e98 10

这已经晚了,但可能对某些人有所帮助.

我已经扩展了@ DarinDimitrov的答案,允许传递第二个对象,它接受任意数量的布尔html属性等disabled="disabled" checked="checked", selected="selected".

仅当属性值为true时才会呈现属性,其他任何内容和属性都不会呈现.

自定义可重用的HtmlHelper:

public static class HtmlExtensions
{
    public static IHtmlString MyTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
                                                                Expression<Func<TModel, TProperty>> expression,
                                                                object htmlAttributes,
                                                                object booleanHtmlAttributes)
    {
        var attributes = new RouteValueDictionary(htmlAttributes);

        //Reflect over the properties of the newly added booleanHtmlAttributes object
        foreach (var prop in booleanHtmlAttributes.GetType().GetProperties())
        {
            //Find only the properties that are true and inject into the main attributes.
            //and discard the rest.
            if (ValueIsTrue(prop.GetValue(booleanHtmlAttributes, null)))
            {
                attributes[prop.Name] = prop.Name;
            }                
        }                                

        return htmlHelper.TextBoxFor(expression, attributes);
    }

    private static bool ValueIsTrue(object obj)
    {
        bool res = false;
        try
        {
            res = Convert.ToBoolean(obj);
        }
        catch (FormatException)
        {
            res = false;
        }
        catch(InvalidCastException)
        {
            res = false;
        }
        return res;
    }

}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用:

@Html.MyTextBoxFor(m => Model.Employee.Name
                   , new { @class = "x-large" , placeholder = "Type something…" }
                   , new { disabled = true})
Run Code Online (Sandbox Code Playgroud)


Nie*_*sma 7

使用RouteValueDictionary解决了这个问题(可以正常工作,因为它基于IDictionary的htmlAttributes)和扩展方法:

public static RouteValueDictionary AddIf(this RouteValueDictionary dict, bool condition, string name, object value)
{
    if (condition) dict.Add(name, value);
    return dict;
}
Run Code Online (Sandbox Code Playgroud)

用法:

@Html.TextBoxFor(m => m.GovId, new RouteValueDictionary(new { @class = "form-control" })
.AddIf(Model.IsEntityFieldsLocked, "disabled", "disabled"))
Run Code Online (Sandbox Code Playgroud)

信用转到/sf/answers/243737861/


Bas*_*ANI 6

如果您不想使用HTML Helper,请看一下我的解决方案

disabled="@(your Expression that returns true or false")"
Run Code Online (Sandbox Code Playgroud)

那个

@{
    bool isManager = (Session["User"] as User).IsManager;
}
<textarea rows="4" name="LetterManagerNotes" disabled="@(!isManager)"></textarea>
Run Code Online (Sandbox Code Playgroud)

我认为更好的方法是检查控制器并将其保存在view(Razor引擎)内部可访问的变量中,以使 the view free from business logic

  • 如果在控件中使用Disabled属性,则无论该属性具有什么值,该控件都将被禁用。即使没有值的属性的存在也​​会禁用控件。 (7认同)
  • 该解决方案确实非常有效,我怀疑拒绝投票的人可能忽略了该表达式为布尔值。当表达式为布尔值时,如果表达式为true,则disable属性将呈现为disabled =“ disabled”;如果为false,则将其完全省略。正是您想要的。 (2认同)