I've done some research on this and seem to find posts that are either outdated or don't quite work in my situation. I may be using wrong keywords when searching though... =/
On my web page I have Tabs containing Group boxes that contain Lines which in turn contain Items. So it is lists of lists 4 levels.
The problem:
When posting back, ViewModel.Tabs is null and I can't save anything. Everything displays quite nicely, but nothing is posted back.
The code
Views/Shared/EditorTemplates/Tab.cshtml
@model AWMCCRM.Web.ViewModels.Tab
@Html.HiddenFor(vm => vm.Name)
<div id="tab-@Model.Name.Replace(" ", string.Empty)" class="tab-content two">
@Html.EditorFor(vm => vm.Groups)
</div>
Views/Shared/EditorTemplates/Group.cshtml
@model AWMCCRM.Web.ViewModels.Group
@Html.HiddenFor(vm => vm.Name)
<fieldset>
<legend>@Model.Name</legend>
@Html.EditorFor(vm => vm.Lines)
</fieldset>
Views/Shared/EditorTemplates/Line.cshtml
@model AWMCCRM.Web.ViewModels.Line
<div class="_100Max">
@Html.HiddenFor(vm => vm.Name)
@Html.EditorFor(vm => vm.Items)
</div>
Views/Shared/EditorTemplates/Item.cshtml
@model AWMCCRM.Web.ViewModels.Item
<div class="_@Model.DisplaySize" title="@Model.Description">
<p>
@Html.HiddenFor(x => x.DataType)
@Html.HiddenFor(x => x.Description)
@Html.HiddenFor(x => x.DisplaySize)
@Html.HiddenFor(x => x.DisplayType)
@Html.HiddenFor(x => x.IDsPiped)
@Html.HiddenFor(x => x.ItemType)
@Html.HiddenFor(x => x.Name)
@Html.LabelFor(vm => vm.Value, Model.Name)
@switch (Model.DisplayType.ToLower().Replace(" ", string.Empty))
{
case "checkbox":
@Html.CheckBoxFor(vm => Convert.ToBoolean(vm.Value))
break;
case "dropdownlist":
@Html.DropDownListFor(vm => vm.Value, Model.ValueOptionListItems)
break;
case "multiselectlist":
@Html.ListBoxFor(
x => x.SelectedValueList,
Model.ValueOptionListItems,
new { id = "itemValuesMultiSelect", multiple = "multiple", Size = 15 })
break;
case "radiobutton":
@Html.RadioButtonFor(vm => vm.Value, Model.Value)
break;
case "textarea":
@Html.TextAreaFor(vm => vm.Value)
break;
default:
@Html.TextBoxFor(vm => vm.Value)
break;
}
</p>
</div>
The ViewModel (cut down version)
namespace AWMCCRM.Web.ViewModels
{
public class PersonEditViewModel
{
public List<Tab> Tabs { get; set; }
//Other properties
//...
}
}
The View (cut down version)
@using (Html.BeginForm("Edit", "Person", FormMethod.Post, new { id = "validate-form", @class = "block-content form" }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x => x.PersonID)
@foreach (var tab in Model.Tabs)
{
@Html.EditorFor(vm => tab)
}
<input class="close-toolbox button" type="submit" value="Save">
}
Any suggestions?
Thanks
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
It's an old article, but it still applies.
I had this exact problem, but basically due to the model binding system you need to use an explicit for loop instead of a foreach loop, and reference your elements by their index.