Disable enable dropdownlistfor based on model prop

2020-05-04 18:57发布

问题:

I am trying to disable or enable a dropdownlistfor in my mvc application based on model property:-

what I am doing is :-

@Html.DropDownListFor(m => m.ParentOrganisationID, new SelectList(Model.ParentOrganisations, "ID", "Name", Model.ParentOrganisationID), new { @id = "ddlParentOrganisations", @class = "form-control css-select", @disabled = Model.IsReadOnly ? "disabled" : "false", @style = "width:40%; height:10%;" })

but even if model property "model.IsReadOnly" is false, then also it is showing the dropdown as disabled.

Please suggest how to handle this, without using any javascript

Thanks in advance

回答1:

It is not possible to include the condition (if/ternary statement(s)) inside the call to the DropDownListFor helper method because you cannot pass a line of c# code (with your if condition) where it expects an object for html attributes. Also all of the below markups will render a disabled SELECT.

<select disabled></select>
<select disabled="disabled"></select>
<select disabled="false"></select>
<select disabled="no"></select>
<select disabled="usingJqueryEnablePlugin"></select>
<select disabled="enabled"></select>

You can simply check the value of your Model property with an if condition and conditionally render the disabled version.

@if (!Model.IsReadOnly)
{
    @Html.DropDownListFor(s => s.ParentOrganisationID, 
                               new SelectList(Model.ParentOrganisations, "ID", "Name"))
}
else
{
    @Html.DropDownListFor(s => s.ParentOrganisationID, 
       new SelectList(Model.ParentOrganisations, "ID", "Name"),new {disabled="disabled"})
}

You may consider creating a custom html helper method which takes care of the if condition checking.

public static class DropDownHelper
{
    public static MvcHtmlString MyDropDownListFor<TModel, TProperty>
                 (this HtmlHelper<TModel> htmlHelper, 
                  Expression<Func<TModel, TProperty>> expression,
                  IEnumerable<SelectListItem> selectItems,
                  object htmlAttributes,
                  bool isDisabled = false)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression,
                                                                    htmlHelper.ViewData);

        IEnumerable<SelectListItem> items =
            selectItems.Select(value => new SelectListItem
            {
                Text = value.Text,
                Value = value.Value,
                Selected = value.Equals(metadata.Model)
            });
        var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
        if (isDisabled && !attributes.ContainsKey("disabled"))
        {
             attributes.Add("disabled", "disabled");
        }
        return htmlHelper.DropDownListFor(expression,items, attributes);
    }
}

Now in your razor view,call this helper

@Html.MyDropDownListFor(s=>s.ParentOrganisationID,
               new SelectList(Model.ParentOrganisations, "ID", "Name")
                                           ,new { @class="myClass"},Model.IsReadOnly)


回答2:

This is an HTML basic rule: from the moment you set the attribute disabled (regardless of its value), the element will be disabled.

To get what you want, you need to create an HTML extension DropDownListFor.

Please see this link.



回答3:

The accepted answer from Shyju works great. But what if you want to use HTML5 data-* attributes in your custom helper? The standard MVC DropDownListFor provides a workaround by using an underscore (_) in place of the dash (-). And that helper is intelligent enough to convert the underscores to dashes when the markup is rendered.

Here is a custom helper that will provide a parameter to disable a DropDownList and also converts the HTML5 data-* attributes appropriately. It also preserves any other values passed in via the htmlAttributes parameter. The code is a little more concise as well (imo).

    public static MvcHtmlString MyDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> list, string optionLabel, object htmlAttributes, bool disabled)
    {
        var routeValues = new System.Web.Routing.RouteValueDictionary();

        // convert underscores to dashes...
        foreach (System.ComponentModel.PropertyDescriptor property in System.ComponentModel.TypeDescriptor.GetProperties(htmlAttributes))
        {
            routeValues.Add(property.Name.Replace('_', '-'), property.GetValue(htmlAttributes));
        }

        if(disabled)
        {
            routeValues.Add("disabled", "disabled");
        }

        return htmlHelper.DropDownListFor(expression, list, optionLabel, routeValues);
    }

And the markup:

@Html.MyDropDownListFor(m => m.MonthId, Model.Months, "Select Month", new { @class = "form-control", data_url = Url.Action("GetMonths") }, Model.IsDisabled)