2009-10-29 1 views
3

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

Сейчас я иду на:

BadgesDropDown.ascx

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

контроллер

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

Является ли это путь?

ответ

0

В 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 делает, то данные, предоставленные для раскрывающегося списка, фиксированы. Другой вариант - это контроллер, который позволяет нам отключать выпадающие данные с другим набором данных, как это требуется.

Существует несколько связанных примеров, которые я нашел:

Nerd ужин

[1]: searcch для codeclimber.net.nz и как к Create-A-DropDownList-с-asp.net- mvc [2]: bradwilson.typepad.com и templates-part-5-master-page-templates

-1

Я реализовал решение, как показано выше. Единственное, что следует отметить, что Помощники должны работать только с данными, поставляемые им, см View dependency

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

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

2

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

Основная концепция заключается в том, что вы определяете небольшую модель представления, которая тесно связана с пользовательским редактором 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 по умолчанию. В нашем примере «Priority.Value». Таким образом, свойство 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; 
    } 
} 

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^