简体   繁体   中英

@Html.DropDownList() Placeholder as Disable and Selected

If I use a @Html.DropDownList() with static values then Placeholder can be created as first option and it is possible to apply Disabled and Selected attribute on this option like this

@Html.DropDownList("month", new List<SelectListItem>
{
    new SelectListItem{ Text="Select Month", Value = "0" , Disabled = true, Selected = true},
    new SelectListItem{ Text="January", Value = "1" },
    new SelectListItem{ Text="February", Value = "2" },
    new SelectListItem{ Text="March", Value = "3" },
    new SelectListItem{ Text="April", Value = "4" },
    new SelectListItem{ Text="May", Value = "5" },
    new SelectListItem{ Text="June", Value = "6" },
    new SelectListItem{ Text="July", Value = "7" },
    new SelectListItem{ Text="August", Value = "8" },
    new SelectListItem{ Text="September", Value = "9" },
    new SelectListItem{ Text="October", Value = "10" },
    new SelectListItem{ Text="November", Value = "11" },
    new SelectListItem{ Text="December", Value = "12" },
}, new {@class = "form-control"})

But if I create dropdown list like with a number range and make a Place holder like this:

@Html.DropDownList("year", 
      Enumerable.Range(1900, 200)
          .Select(i => new SelectListItem { Text = i.ToString(), Value = i.ToString() }), 
      "Please Select Year", new { @class = "form-control" })

Is it possible to make this Please Select Year Disabled and Selected?

这是第一个下拉列表的输出,其中第一个选项已禁用

我想要这个请选择年份为禁用

Note the overload you're using for year drop down gives you no control over the default item appearance.

However you could revert to the same approach you are using for months, with a tiny bit of code:

@{
    var years = new List<SelectListItem>{
        new SelectListItem{ Text="Select Year", Value = "0" , Disabled = true, Selected = true},
    };

    years.AddRange(Enumerable.Range(1900, 200)
          .Select(i => new SelectListItem { Text = i.ToString(), Value = i.ToString() }));
}

@Html.DropDownList("year", 
      years, 
      new { @class = "form-control" })

DropDownListFor allows to specify a placeholder, but the resulting option is not selected, neither disabled.

I've come up with this

public static MvcHtmlString CustomDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, IEnumerable<SelectListItem> items, string placeHolder, object htmlAttributes)
{
    var r = htmlHelper.DropDownListFor(expression, items, placeHolder, htmlAttributes).ToString();
    var loc = r.IndexOf(placeHolder);
    r = r.Insert(loc - 1, $" selected disabled");
    return new MvcHtmlString(r);
}

Of course, if you want something more reliable, perhaps use HtmlAgilityPack for the parsing.

With a loose basis on another answer, I've written a few extensions to HtmlHelper that make this easy to implement.

To implement in the code, just use as follows:

@Html.DropDownListWithDisabledFirstItemFor(model => model.MyProperty, new SelectList(source, "ID_Property", "Display_Property"), "Select an item")

Change:

  • model.MyProperty to the property name from your model\\viewmodel.
  • source to the source collection for your drop down list.
  • ID_Property to the name of the ID property on the type in source .
  • Display_Property to the name of the display property on the type in source .
  • Select an item to the text you want to appear in the disabled item in the drop down list.

There are overloads of the DropDownListWithDisabledFirstItemFor method that allow for specification of HTML attributes too. The extensions could be further overloaded if other versions of DropDownListFor are required.

Why this and not the accepted answer?

I don't like the idea that I can specify and option label for my drop down list but have it enabled. The built-in functionality should offer the ability to automatically disable it without having to manually add a SelectListItem to do it.

In addition, I really dislike the idea of using JavaScript on the client to disable the first option in the select (which is a suggestion in another post). That feels like a total hack to me.

This implementation allows for the continued use of the option label without having to do anything to the SelectList .

Extension Code

The extension code is in the HtmlHelperExtensions class below:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;

/// <summary>
/// A class that defines extension methods for a HTML helper.
/// </summary>
public static class HtmlHelperExtensions
{
    #region Methods
    #region _Private_
    private static MvcHtmlString DisableDropDownItem(MvcHtmlString source, string sourceItemName, string sourceItemValue = "", string targetItemValue = "")
    {
        string htmlString;
        MvcHtmlString returnValue;
        string sourceString;

        sourceString = $"<option value=\"{sourceItemValue}\">{sourceItemName}</option>";

        htmlString = source.ToHtmlString();
        if (htmlString.Contains(sourceString))
        {
            string replaceString;

            replaceString = $"<option value=\"{targetItemValue}\" disabled=\"disabled\" selected=\"selected\">{sourceItemName}</option>";
            htmlString = htmlString.Replace(sourceString, replaceString);
        }
        returnValue = new MvcHtmlString(htmlString);

        return returnValue;
    }

    #endregion
    #region _Public_
    /// <summary>
    /// Returns an HTML select element for each property in the object that is represented by the specified expression using the specified list items, and option label, with the opton label disabled.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the value.</typeparam>
    /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
    /// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
    /// <param name="selectList">An IEnumerable of SelectListItem objects that are used to populate the drop-down list.</param>
    /// <param name="optionLabel">A string containing the text for a default empty item. This parameter can be null.</param>
    /// <param name="optionLabelValue">A string containing the value that should be assigned to the option label.</param>
    /// <returns>An HTML select element for each property in the object that is represented by the expression.</returns>
    public static MvcHtmlString DropDownListWithDisabledFirstItemFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, int optionLabelValue = 0)
    {
        return DisableDropDownItem(htmlHelper.DropDownListFor(expression, selectList, optionLabel), optionLabel, string.Empty, optionLabelValue.ToString());
    }
    /// <summary>
    /// Returns an HTML select element for each property in the object that is represented by the specified expression using the specified list items, option label, and HTML attributes, with the opton label disabled.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the value.</typeparam>
    /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
    /// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
    /// <param name="selectList">An IEnumerable of SelectListItem objects that are used to populate the drop-down list.</param>
    /// <param name="optionLabel">A string containing the text for a default empty item. This parameter can be null.</param>
    /// <param name="htmlAttributes">An IDictionary of key string and value object that contains the HTML attributes to set for the element.</param>
    /// <param name="optionLabelValue">A string containing the value that should be assigned to the option label.</param>
    /// <returns>An HTML select element for each property in the object that is represented by the expression.</returns>
    public static MvcHtmlString DropDownListWithDisabledFirstItemFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, IDictionary<string, object> htmlAttributes, int optionLabelValue = 0)
    {
        return DisableDropDownItem(htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes), optionLabel, string.Empty, optionLabelValue.ToString());
    }
    /// <summary>
    /// Returns an HTML select element for each property in the object that is represented by the specified expression using the specified list items, option label, and HTML attributes, with the opton label disabled.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the value.</typeparam>
    /// <param name="htmlHelper">The HTML helper instance that this method extends.</param>
    /// <param name="expression">An expression that identifies the object that contains the properties to display.</param>
    /// <param name="selectList">An IEnumerable of SelectListItem objects that are used to populate the drop-down list.</param>
    /// <param name="optionLabel">A string containing the text for a default empty item. This parameter can be null.</param>
    /// <param name="htmlAttributes">An object that contains the HTML attributes to set for the element.</param>
    /// <param name="optionLabelValue">A string containing the value that should be assigned to the option label.</param>
    /// <returns>An HTML select element for each property in the object that is represented by the expression.</returns>
    public static MvcHtmlString DropDownListWithDisabledFirstItemFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel, object htmlAttributes, string optionLabelValue = "0")
    {
        return DisableDropDownItem(htmlHelper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes), optionLabel, string.Empty, optionLabelValue);
    }

    #endregion
    #endregion
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM