2010-11-10 15 views
11

Zastanawiam się, czy ktoś może rzucić nieco światła na ten problem ..Optgroup rozwijanej wsparcie w MVC - Problemy z modelu wiązania

Mam grupę opcja rozwijaną do wybierania rasa osoby - jednak to nie zapisywanie wartości w modelu.

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

To mój 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)%> 

I w widoku mam przedstawieniu go jako:

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

Jednak to nie przechodząc przez wybraną wartość do modelu ... ma ktoś doświadczył podobnych problemów ... Wielu z góry dzięki za wskazówki .

+0

Tylko uwaga - Próbowałem to również z ciąg zamiast int jako wartość opcji i nadal nie wiąże. – beebul

+0

Proszę sprawdzić [Teraz wsparcie dla Optgroup na liście rozwijanej .Net MVC] (http://www.jquery2dotnet.com/2014/01/html5-dropdownlist-optgroup-tag-in-mvc.html) – Sender

Odpowiedz

8

Twoja select nie ma atrybutu name, więc po przesłaniu formularza wybrana wartość nie zostanie wysłana na serwer. Trzeba dodać nazwę:

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

Wielkie dzięki Darin - pracował Uczta ... :-) – beebul

5

właśnie zmienił klasę pomocnika, aby pracować dla MVC 3 oraz z wartości pustych int. Dziękuję bardzo za zajęcia, oszczędzam mnóstwo czasu.

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

ta jest obsługiwana natywnie za pomocą SelectListGroup jak z 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 }); 

Następnie w MVC, czy

@Html.DropDownList("select", items)