Search code examples
c#asp.net-mvcasp.net-mvc-3mvc-editor-templatesigrouping

How to Display IEnumerable<IGrouping<string, Model>> with an editor template


I have a bunch of items that I have grouped up by Header.

I would like to display them on the page with the header text followed by the editor template for each individual item.

I tried using nested templates as follows:

Main Page:

@Html.EditorFor(x => x.GroupedItems, "ListofGrouping");

ListofGrouping Editor Template:

@model IList<IGrouping<string, Model>>
@for(int i = 0; i < Model.Count(); i++)
{
    @Html.EditorFor(x => x[i],"IGrouping")
}

IGrouping Editor Template:

@model IGrouping<string, Model>

@Html.DisplayFor(x => x.Key)
@Html.EditorForModel()

This works up till the last line. I get all the header values but the individual items are not displayed.

If I can't get it to work this way I will just use a data grid and do the grouping there, but I figured this should be possible in MVC3.


Solution

  • Update: You must write your own EditorTemplate for IGrouping.

    Sample of EditorTemplate for IGrouping: Model:

    public class Row
    {
        public Row()
        {
        }
    
        public Row(string key, int value)
        {
            Key = key;
            Value = value;
        }
    
        public int Value { get; set; }
    
        public string Key { get; set; }
    }
    

    Controller:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";
            IEnumerable<Row> dict = new[] { new Row("1", 1), new Row("1", 2), new Row("1", 3), new Row("2", 2), new Row("2", 3), new Row("2", 4) };
            var grouped = dict.GroupBy(c => c.Key).First();
            //var grouplist = grouped.Select(c => new KeyValuePair<string, IEnumerable<int>> (c.Key, c.Select(b=>b.Value)));
            return View(grouped);
        }
    
        public ActionResult Post(IEnumerable<Row> Model)
        {
            return null;
        }
    }
    

    View Index:

    @model IGrouping<string, MvcApplication1.Models.Row>
    @{
        ViewBag.Title = "Home Page";
    }
    
    @using(Html.BeginForm("Post", "Home", FormMethod.Post))
    {
        @Html.EditorForModel("IGrouping")
        <button type="submit">Submit</button>
    }
    

    EditorTemplate IGrouping.cshtml:

    @model IGrouping<string, MvcApplication1.Models.Row>
    @{
        @Html.DisplayFor(m => m.Key)
        int i = 0;
        foreach (var pair in Model.Select(c => c))
        {
            @Html.Hidden(string.Format("Model[{0}].Key", i), pair.Key)
            @Html.TextBox(string.Format("Model[{0}].Value", i), pair.Value)
            i++;
        }
    }
    

    More about binding Collections you can read there:Hancelman's blog