Условно отключить Html.DropDownList - PullRequest
18 голосов
/ 19 января 2010

Как я могу изменить это объявление DropDownList так, чтобы отключенный атрибут был включен / отключен условно?

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

нерабочий пример:

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

ps добавление условия if вокругвесь оператор не является желаемым подходом:)

РЕДАКТИРОВАТЬ: на основе этот метод расширения из другого вопроса Я придумал следующее расширение:

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

, который затем можно использовать как

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

Ответы [ 7 ]

28 голосов
/ 03 июня 2013

Нет необходимости добавлять вспомогательные методы, вы можете просто использовать

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

Если вы удалите записи as object, это не сработает, потому что по умолчанию new {} является динамическим объектомкомпилируется во время выполнения, поэтому два возможных объекта должны иметь одинаковые свойства.Но параметр атрибутов Html на самом деле является просто объектом, поэтому эту динамику можно привести как объекты, чтобы обойти это.

Это решение даже позволяет использовать несколько атрибутов HTML, где один необязательный, а другой - нет, т.е.class='whatever' не является обязательным, но disabled означает, что вы помещаете class='whatever' в оба объекта, но необязательный только в первый.Ответ Димитрова не поддерживает никаких пользовательских атрибутов, кроме отключенных.

19 голосов
/ 19 января 2010

Пожалуйста, не пишите код для спагетти.Для этой цели существуют 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" });
}

А затем:

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

Или, может быть, вы могли бы придумать что-нибудь еще лучше (если модель содержит опции):

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

Вы также получите бонус, имея больше кода для тестирования юнитов.

9 голосов
/ 18 декабря 2012

Одним из вариантов является создание пользовательской версии Html.DropDownList, которая принимает дополнительный параметр и делает то, что вы хотите ... но тогда вам придется создать новую для каждого типа помощника - TextBoxFor, TextAreaFor, CheckBoxFor и т. Д. ... и вы все еще должны выяснить, как заставить это работать.

Вместо этого я решил создать Html Helper для замены обычного анонимного объекта HtmlAttributes, поскольку тогда он будет совместим со всеми хелперами, которые используют HtmlAttributes без какой-либо специальной работы. Это решение также позволяет вам проходить через дополнительные атрибуты, такие как класс, имя или что угодно. Он не блокирует вас только для инвалидов.

Я создал следующий Помощник - он принимает логический и анонимный объект. Если для параметра disabled установлено значение true, он добавляет атрибут disabled в анонимный объект (который фактически является словарем) со значением «disabled», в противном случае он вообще не добавляет свойство.

public static RouteValueDictionary ConditionalDisable(
   bool disabled, 
   object htmlAttributes = null)
{
   var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

   if (disabled)
      dictionary.Add("disabled", "disabled");

   return dictionary;
}


Пример этого в действии:

@Html.TextBoxFor(m => m.SomeProperty,    
   HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))

1011 *
*

Одним из огромных преимуществ этого подхода для меня было то, что он работает практически со всеми MVC HtmlHelpers, поскольку все они имеют перегрузки, которые принимают RouteValueDictionary вместо анонимного объекта.

Предостережения
HtmlHelper.AnonymousObjectToHtmlAttributes () использует некоторую причудливую работу кода ниндзя, чтобы добиться цели. Я не совсем уверен, насколько он эффективен ... но этого было достаточно для того, для чего я его использую. Ваш пробег может отличаться.

Мне не особенно нравится его название - но я не мог придумать ничего лучше. Переименовать легко.

Мне также не нравится синтаксис использования - но опять же я не мог придумать ничего лучшего. Это не должно быть сложно изменить. Метод расширения для object - это одна идея ... вы в конечном итоге получите new { @class = "someClass" }.ConditionalDisable(true), но тогда, если вам нужен только атрибут disable и у вас нет ничего дополнительного, вы получите что-то грубое, например new {}.ConditionalDisable(true); и вы также получаете метод расширения, который обнаруживается для всех объектов ... что, вероятно, нежелательно.

2 голосов
/ 18 июля 2015
@bool IsEditable=true;

@if (IsEditable)
{
    Html.DropDownListFor(m => m, selectList);
}
else
{
    Html.DropDownListFor(m => m, selectList, new { disabled = "disabled" })
}
0 голосов
/ 22 марта 2018

Для полноты здесь есть один, который сохраняет все параметры и отправляет выбранное значение на сервер:

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

Пример использования, отключить раскрывающийся список, если в списке только один элемент, одно значение все еще отправляется на сервер с правильным идентификатором клиента:

@Html.DropDownListFor(m => m.SomeValue, Model.SomeList, new { @class = "some-class" }, Model.SomeList > 1)
0 голосов
/ 24 января 2014

Строго набранная версия:

 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" });
    }
0 голосов
/ 19 января 2010

Я не знаю, предлагает ли ASP.NET более лаконичный подход для особых случаев, но, вероятно, вы могли бы сделать:

<%= Html.DropDownList("Quantity", new SelectList(...), Model.CanEdit? new{@class="quantity"} : new{@class="quantity", @disabled:"disabled"}) %>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...