2010-11-10 2 views
11

Интересно, если кто-то может пролить некоторый свет на эту проблему ..OPTGROUP раскрывающийся поддержку MVC - Проблемы с Model Binding

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

ViewModel

[UIHint("EthnicOriginEditorTemplate")] 
    [DisplayName("Question 6: Ethnic Origin")] 
    public int EthnicOrigin { get; set; } 

Helper: GroupDropList.Cs

using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Web.Mvc; 
using System.Web.Routing; 

namespace Public.Helpers 
{ 
    public static class GroupDropListExtensions 
    { 
     public static string GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int SelectedValue, object htmlAttributes) 
     { 
      if (data == null && helper.ViewData != null) 
       data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>; 
      if (data == null) return string.Empty; 

      var select = new TagBuilder("select"); 

      if (htmlAttributes != null) 
       select.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 

      select.GenerateId(name); 

      var optgroupHtml = new StringBuilder(); 
      var groups = data.ToList(); 
      foreach (var group in data) 
      { 
       var groupTag = new TagBuilder("optgroup"); 
       groupTag.Attributes.Add("label", helper.Encode(group.Name)); 
       var optHtml = new StringBuilder(); 
       foreach (var item in group.Items) 
       { 
        var option = new TagBuilder("option"); 
        option.Attributes.Add("value", helper.Encode(item.Value)); 
        if (SelectedValue != 0 && item.Value == SelectedValue) 
         option.Attributes.Add("selected", "selected"); 
        option.InnerHtml = helper.Encode(item.Text); 
        optHtml.AppendLine(option.ToString(TagRenderMode.Normal)); 
       } 
       groupTag.InnerHtml = optHtml.ToString(); 
       optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal)); 
      } 
      select.InnerHtml = optgroupHtml.ToString(); 
      return select.ToString(TagRenderMode.Normal); 
     } 
    } 

    public class GroupDropListItem 
    { 
     public string Name { get; set; } 
     public List<OptionItem> Items { get; set; } 
    } 

    public class OptionItem 
    { 
     public string Text { get; set; } 
     public int Value { get; set; } 
    } 
} 

Это мой EditorTemplate

<%@ Import Namespace="Public.Helpers"%> 
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int>"%> 

<%=Html.GroupDropList("EthnicOrigin", 
           new[] 
            {           
             new GroupDropListItem 
              { 
               Name = "Ethnicity", 
               Items = new List<OptionItem> 
                 { 
                  new OptionItem {Value = 0, Text = "Please Select"} 
                 } 
              }, 

             new GroupDropListItem 
              { 
               Name = "a) White", 
               Items = new List<OptionItem> 
                 { 
                  new OptionItem {Value = 1, Text = "British"}, 
                  new OptionItem {Value = 2, Text = "Irish"}, 
                  new OptionItem {Value = 3, Text = "Other White (Please specify below)"} 
                 } 
              }, 

             --snip 

            }, Model, null)%> 

И в представлении я ссылаться на него как:

<%=Html.EditorFor(x => x.EthnicOrigin, "EthnicOriginEditorTemplate")%> 

Однако это не проходит через выбранное значение в модели ... кто-нибудь сталкивались с подобными проблемами ... много спасибо заранее за несколько указателей ,

+0

Просто к сведению - я также попытался это с string вместо int в качестве значения параметра, и он по-прежнему не связывается. – beebul

+0

Пожалуйста, проверьте [Now Support for Optgroup In Dropdownlist .Net MVC] (http://www.jquery2dotnet.com/2014/01/html5-dropdownlist-optgroup-tag-in-mvc.html) – Sender

ответ

8

Ваш select не имеет атрибута name, поэтому при отправке формы выбранное значение не отправляется на сервер. Вам необходимо добавить имя:

select.GenerateId(name); 
select.MergeAttribute("name", name); 
+0

Большое спасибо Дарин - работал угощение ... :-) – beebul

5

Просто изменил класс-помощник, чтобы он работал для MVC 3 и с нулевым int. Большое спасибо за класс, сэкономит мне много времени.

public static class GroupDropListExtensions 
{ 
    public static MvcHtmlString GroupDropList(this HtmlHelper helper, string name, IEnumerable<GroupDropListItem> data, int? SelectedValue, object htmlAttributes) 
    { 
     if (data == null && helper.ViewData != null) 
      data = helper.ViewData.Eval(name) as IEnumerable<GroupDropListItem>; 
     if (data == null) return new MvcHtmlString(string.Empty); 

     var select = new TagBuilder("select"); 

     if (htmlAttributes != null) 
      select.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 

     select.GenerateId(name); 
     select.MergeAttribute("name", name); 

     var optgroupHtml = new StringBuilder(); 
     var groups = data.ToList(); 
     foreach (var group in data) 
     { 
      var groupTag = new TagBuilder("optgroup"); 
      groupTag.Attributes.Add("label", helper.Encode(group.Name)); 
      var optHtml = new StringBuilder(); 
      foreach (var item in group.Items) 
      { 
       var option = new TagBuilder("option"); 
       option.Attributes.Add("value", helper.Encode(item.Value)); 
       if (SelectedValue != 0 && item.Value == SelectedValue) 
        option.Attributes.Add("selected", "selected"); 
       option.InnerHtml = helper.Encode(item.Text); 
       optHtml.AppendLine(option.ToString(TagRenderMode.Normal)); 
      } 
      groupTag.InnerHtml = optHtml.ToString(); 
      optgroupHtml.AppendLine(groupTag.ToString(TagRenderMode.Normal)); 
     } 
     select.InnerHtml = optgroupHtml.ToString(); 
     return new MvcHtmlString(select.ToString(TagRenderMode.Normal)); 
    } 
} 

public class GroupDropListItem 
{ 
    public string Name { get; set; } 
    public List<OptionItem> Items { get; set; } 
} 

public class OptionItem 
{ 
    public string Text { get; set; } 
    public int Value { get; set; } 
} 
1

Это изначально поддерживается с помощью SelectListGroup от ASP.NET MVC 5.2:

var items = new List<SelectListItem>(); 
var group1 = new SelectListGroup() { Name = "Group 1" }; 
items.Add(new SelectListItem() { Text = "Item1", Group = group1 }); 

Тогда в MVC, сделать

@Html.DropDownList("select", items)