如何使 EditorFor 有条件只读?

问题描述 投票:0回答:8

我有这行代码:

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })

我的视图数据字典中有一个名为 Readonly 的变量。如何在

ViewBag.Readonly
为 true 时使 Quantity 只读,而仅在为 false 时不只读?

简单的事情,但是 Razor 与 HTML(这是古老的)的结合使得原本简单的事情变得不可能。

编辑:

我不想使用 if 语句。这是最后的手段,因为它违反了 DRY,我过去曾多次因为不遵守而被严重烧伤。

我上面的行确实有效,因为它使文本框变为只读。我需要根据我的视图状态来设置这个条件。

解决方案:

我使用过以下内容。它仍然是 DRY 违规,但将其减少到一行。

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = ViewBag.Readonly ? (object)new { @class = "form-control", @readonly = "htmlsucks" } : (object)new { @class = "form-control" } })
asp.net-mvc html asp.net-mvc-5
8个回答
32
投票

编辑:MVC 5

控制器

ViewBag.Readonly=true;//false

查看

@Html.EditorFor(model => model.Quantity, ViewBag.Readonly ? (object)new { htmlAttributes = new { @readonly = "readonly", @class = "form-control" }} : new { htmlAttributes = new { @class = "form-control" } })

6
投票

今天我必须处理这个问题,因为我必须动态地为

Html.TextBoxFor
元素设置“只读”属性。我最终编写了以下辅助方法,该方法使我能够在保持 DRY 方法的同时解决问题:

/// <summary>
/// Gets an object containing a htmlAttributes collection for any Razor HTML helper component,
/// supporting a static set (anonymous object) and/or a dynamic set (Dictionary)
/// </summary>
/// <param name="fixedHtmlAttributes">A fixed set of htmlAttributes (anonymous object)</param>
/// <param name="dynamicHtmlAttributes">A dynamic set of htmlAttributes (Dictionary)</param>
/// <returns>A collection of htmlAttributes including a merge of the given set(s)</returns>
public static IDictionary<string, object> GetHtmlAttributes(
    object fixedHtmlAttributes = null,
    IDictionary<string, object> dynamicHtmlAttributes = null
    )
{
    var rvd = (fixedHtmlAttributes == null)
        ? new RouteValueDictionary()
        : HtmlHelper.AnonymousObjectToHtmlAttributes(fixedHtmlAttributes);
    if (dynamicHtmlAttributes != null)
    {
        foreach (KeyValuePair<string, object> kvp in dynamicHtmlAttributes)
            rvd[kvp.Key] = kvp.Value;
    }
    return rvd;
}

可以通过以下方式使用:

var dic = new Dictionary<string,object>();
if (IsReadOnly()) dic.Add("readonly", "readonly");
Html.TextBoxFor(m => m.Name, GetHtmlAttributes(new { @class="someclass" }, dic))

代码非常不言自明,但是我还在我的博客上的这篇文章中解释了底层逻辑。


5
投票

非常简单。这样做。

@if((bool)ViewBag.Readonly)
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
}
else
{
    @Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { @class = "form-control" } })
}

2
投票

如果你的视图中有很多地方都有这样的逻辑,我认为使用库FluentDataAnnotations可以让你的代码干净整洁。

如果您熟悉FluentValidator,那么使用起来非常相似。

在您的情况下,所有逻辑都将从视图移动到模型注释类。你只会拥有

@Html.EditorFor(model => model.Quantity)

它甚至允许在条件下使用模型属性 例如

this.When(model => !model.AllowEditPhone,
 () => {
     this.For(m => m.Phone).SetReadOnly(false);
 });

这里是需要 ASP.NET MVC 5 的 NuGet 包。 (对 ASP.NET Core 的支持正在进行中。)


1
投票

通过编写辅助方法,可以尊重 DRY 原则。

    using System.Web.Mvc.Html;

    public static MvcHtmlString Concat(this MvcHtmlString first, params MvcHtmlString[] strings)
    {
        return MvcHtmlString.Create(first.ToString() + string.Concat(strings.Select(s => ( s == null ? "" : s.ToString()))));
    }

    public static MvcHtmlString ConditionalEditFor<TModel,TValue>(this HtmlHelper<TModel> helper, bool EditCondition, Expression<Func<TModel, TValue>> Expression)
    {
        helper.ConditionalEditFor(EditCondition,Expression,false);
    }

    public static MvcHtmlString ConditionalEditFor<TModel, TValue>(this HtmlHelper<TModel> helper, bool EditCondition, Expression<Func<TModel, TValue>> Expression, bool IncludeValidationOnEdit)
    {
        if (EditCondition)
        {
            if (!IncludeValidationOnEdit)
                return EditorExtensions.EditorFor<TModel, TValue>(helper, Expression);
            else
                return EditorExtensions.EditorFor<TModel, TValue>(helper, Expression).Concat(ValidationExtensions.ValidationMessageFor<TModel, TValue>(helper, Expression));
        }
        else
        {
            return DisplayExtensions.DisplayFor<TModel, TValue>(helper, Expression);
        }
    }

那么在你看来:

添加条件语句判断只读 例如

@{bool IsReadOnly = YourCondition;}

@Html.ConditionalEditFor(!IsReadOnly/*condition*/, model => model.YourProperty,true /*do validation*/)

然后您可以添加您想要的任何其他覆盖。


1
投票

JQUERY 读取 SETUP_TYPE 控件值并使用特定 CSS 选择器禁用控件。

$(function () {
    if ($("#SETUP_TYPE").val() == "1") { $('.XXX').attr('disabled', true); }
})

$(function () {
    if ($("#SETUP_TYPE").val() == "2") { $('.YYY').attr('disabled', true); }
})

如果 SETUP_TYPE 为 1 或 2,则禁用此控件。

@Html.EditorFor(model => model.CLAIM, new { htmlAttributes = new { @class = "form-control XXX YYY" } })

如果 SETUP_TYPE 为 1,则禁用此控件。

@Html.EditorFor(model => model.POLICY, new { htmlAttributes = new { @class = "form-control XXX" } })

如果 SETUP_TYPE 为 2,则禁用此控件。

@Html.EditorFor(model => model.INSURED, new { htmlAttributes = new { @class = "form-control YYY" } })

0
投票

您可以编写带有附加参数的 IHtmlHelper 扩展:

public static IHtmlContent ReadonlyishTextBoxFor<TModel, TProperty>(this IHtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null, bool shouldBeReadonly = false)
{
    var attributes = new Dictionary<string, object>();
    if (htmlAttributes != null)
    {
        foreach (var propertyInfo in htmlAttributes.GetType().GetProperties())
        {
            attributes.Add(propertyInfo.Name, propertyInfo.GetValue(htmlAttributes));
        }
    }

    if (shouldBeReadonly)
    {
        attributes.Add("readonly", "readonly");
    }

    return helper.TextBoxFor(expression, format: null, attributes);
}

剃须刀:

@Html.ReadonlyishTextBoxFor(p => p.Email, new { @class = "form-control" }, true )
@Html.ReadonlyishTextBoxFor(p => p.Email, new { @class = "form-control" } )

0
投票

老问题,但今天正在看这个 - 所以我想无论如何都会添加一个答案。

html 助手接受 html 属性作为对象或 IDictionary

这意味着我们可以添加代码来构造变量的属性,然后将其传入。

例如

@{
    var htmlAttributes = new Dictionary<string, object>()
    {
        { "@class", "form-control" }
    };

    if (ViewBag.Readonly) htmlAttributes.Add("@readonly", "readonly");
}

@Html.EditorFor(model => model.Quantity, new { htmlAttributes = htmlAttributes })    
© www.soinside.com 2019 - 2024. All rights reserved.