Вопрос

Используя шаблонные помощники в MVC2.0, я столкнулся с дилеммой: как заставить элементы заполнить раскрывающийся список.я использую [UIHint(BadgesDropDown)] Атрибут, но как мне получить элементы списка, не нарушая шаблон MVC, должен ли контроллер поместить их в ViewData?Должен ли BadgesDropDown.ascx вызвать помощника, чтобы получить их?

Прямо сейчас я собираюсь:

ЗначкиDropDown.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.DropDownList("", ViewData["Badges"] as IEnumerable<SelectListItem>)%>

Контроллер

ViewData["Badges"] = new SelectList(SiteRepository.GetBadges(), "RowKey", "BadgeName");

Это путь?

Это было полезно?

Решение

В MVC 2 отличный новый метод...который, если он используется, опирается на все данные атрибутов.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<glossaryDB.EntityClasses.AssociationEntity>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Association: Edit
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
    <h3>Association: Edit</h3>
    <% using (Html.BeginForm()) { %>
        <fieldset style="padding: 1em; margin: 0; border: solid 1px #999;">
            <%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
            <%= Html.EditorForModel() %>
            <input type="submit" value="  Submit  " />
        </fieldset>
    <% } %>
    <p><%= Html.ActionLink("Details", "Index") %></p>
</asp:Content>

Чтобы это работало, есть 2 варианта.Либо UIHint должен предоставить источник данных, либо контроллер должен это сделать.Если UIHint это делает, данные, представленные в раскрывающемся списке, фиксируются.Другой вариант — контроллер, который позволяет нам переключать данные раскрывающегося списка на другой набор данных по мере необходимости.

Я нашел несколько связанных примеров:

Ужин ботаника

[1]:searcch для codeclimber.net.nz и how-to-create-a-dropdownlist-with-asp.net-mvc [2]:bradwilson.typepad.com и templates-part-5-master-page-templates

Другие советы

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

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

В вашем примере мы начнем с (дочерней) ViewModel, специфичной для одного списка выбора:

public class SelectModel
{
  #region SelectModel(string value, IEnumerable<SelectListItem> items)
  public SelectModel(string value, IEnumerable<SelectListItem> items)
  {
    _value = value;
    Items = new List<SelectListItem>(items);

    _Select();
  } 
  #endregion

  // Properties

  public List<SelectListItem> Items { get; private set; }

  public string Value
  { 
    get { return _value; }
    set { _value = value; _Select();}
  }
  private string _value;

  // Methods

  private void _Select()
  {
    Items.ForEach(x => x.Selected = (Value != null && x.Value == Value));
  }
}

В модели представления, которая хочет использовать раскрывающийся список, вы составляете модель выбора (мы все используем модели представления, верно?):

public class EmailModel
{
  // Constructors

  public EmailModel()
  {
    Priority = new SelectModel("normal", _ToPrioritySelectItems());
  }

  // Properties

  public SelectModel Priority { get; set; }

  // Methods

  private IEnumerable<SelectListItem> _ToPrioritySelectItems()
  {
    List<SelectListItem> result = new List<SelectListItem>();

    result.Add(new SelectListItem() { Text = "High", Value = "high" });
    ...
  }

Обратите внимание, что это простой пример с фиксированным набором раскрывающихся элементов.Если они поступают с уровня домена, контроллер передает их в ViewModel.

Затем добавьте шаблон редактора SelectModel.ascx в Shared/EditorTemplates.

<%@ Control Inherits="System.Web.Mvc.ViewUserControl<SelectModel>" %>

<div class="set">
  <%= Html.LabelFor(model => model) %>
  <select id="<%= ViewData.ModelMetadata.PropertyName %>_Value" name="<%=ViewData.ModelMetadata.PropertyName %>.Value">
  <% foreach (var item in Model.Items) { %>
    <%= Html.OptionFor(item) %>
  <% } %>
  </select>
</div>

Примечание:OptionFor — это специальное расширение, которое делает очевидное

Хитрость здесь в том, что идентификатор и имя задаются с использованием составного формата, который ожидает ModelBinder по умолчанию.В нашем примере «Приоритет.Значение».Таким образом, свойство Value на основе строки, определенное как часть SelectModel, устанавливается напрямую.Установщик позаботится об обновлении списка элементов, чтобы установить параметр выбора по умолчанию, если нам нужно повторно отобразить форму.

В чем действительно хорош подход «дочерней модели представления», так это в более сложных «управляющих фрагментах разметки».Теперь у меня есть модели дочерних представлений, которые используют аналогичный подход для списков MultiSelect, диапазонов дат начала и окончания и комбинаций даты и времени.

Как только вы пойдете по этому пути, следующим очевидным вопросом станет подтверждение.

В итоге все мои дочерние модели ViewModel реализовали стандартный интерфейс:

public interface IValidatable
{
  bool HasValue { get; }
  bool IsValid { get; }
}

Затем у меня есть собственный ValidationAttribute:

public class IsValidAttribute : ValidationAttribute
{
  // Constructors

  public IsValidAttribute()
  {
    ErrorMessage = "(not valid)";
  }

  // Properties

  public bool IsRequired { get; set; }

  // Methods

  private bool Is(object value)
  {
    return value != null && !"".Equals(value);
  }

  public override bool IsValid(object value)
  {
    if (!Is(value) && !IsRequired)
      return true;

    if (!(value is IValidatable))
      throw new InvalidOperationException("IsValidAttribute requires underlying property to implement IValidatable");

    IValidatable validatable = value as IValidatable;
    return validatable.IsValid;
  }
}

Теперь вы можете просто поместить атрибуты в свойства, которые являются дочерними ViewModel, как и любое скалярное свойство:

[IsValid(ErrorMessage = "Please enter a valid start date/time")]
public DateAndTimeModel Start { get; set; }

Я реализовал решение, как показано выше.Следует отметить одну вещь: помощники должны работать только с предоставленными им данными, см. Посмотреть зависимость

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

Я согласен с приведенным выше утверждением.Просто по сравнению с обычной разработкой ASP.Net нужно проделать большую работу.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top