0

I am trying to generate Two sets of List of checkboxes on a view. It all working apart from Post action. On submit, ParentViewModel is not binding the ChildViewModel properly Model. FirstCheckboxList Model. SecondCheckboxList Above both are coming as null.

I am not sure what I am missing. Any help on this would be great. Thanks in advance.

CheckboxItems.cshtml

@model List<CheckboxItem>
@{        
    for (int i = 0; i < Model.Count(); i++)
    {
       <div>
       @Html.CheckBoxFor(x => x.ElementAt(i).Checked, new { @id = Model.ElementAt(i).Id, onclick = "GetValue()" })
          <span id="Padded">@Model.ElementAt(i).Text</span>
       </div> 
    }
}

MainView.cshtml

 @Html.BeginForm(){     
       @Html.EditorFor(m=> m.FirstCheckboxList,"CheckboxItems") 
       @Html.EditorFor(m=> m.SecondCheckboxList, "CheckboxItems")                
 }
 @Html.TextBoxFor(m => m.FSelected, new Dictionary<string,object>() {{"readonly",true}})       
 @Html.TextBoxFor(m => m.FUniverse,new Dictionary<string,object>() {{"readonly",true}})
        <input type="submit" name="nextBtn" value ="Next" />
 }

ParentViewModel

public class ParentViewModel
{       
    public int PId { get; set; }
    public IEnumerable<CheckboxItem> FirstCheckboxList{ get; set; }
    public IEnumerable<CheckboxItem> SecondCheckboxList{ get; set; }
    public Int64 FSelected { get; set; }
    public Int64 FUniverse { get; set; }
}

CheckboxItem : child view model

 public class CheckboxItem
  {
    public int Id { get; set; }
    public string Text { get; set; }
    public bool Checked { get; set; }
  }

controller action

   [HttpPost]
    public ActionResult MyCheckboxView(int planid,   ParentViewModel model, string nextBtn)
    {
        // do something
        return View(Model);
    }
kum123
  • 3
  • 2
  • 1
    checkbox names should be like firstchecboxlist[i].fieldname.. look at the html that is rendered – maxlego Apr 29 '13 at 16:00

1 Answers1

1

Try changing your viewmodel for the ParentViewModel to use a List<CheckboxItem> instead of an IEnumerable<CheckboxItem>:

public class ParentViewModel
{       
    public int PlanId { get; set; }
    public List<CheckboxItem> FirstCheckboxList{ get; set; }
    public List<CheckboxItem> SecondCheckboxList{ get; set; }
    public Int64 FSelected { get; set; }
    public Int64 FUniverse { get; set; }
}

The model binder needs a data structure like a List or an Array so that it can correctly bind elements at specified indexes. IEnumerable is just an interface and doesn't support indexes like this.

Edit

Also, as a side-note, you don't have to bother with the for loop in your EditorTemplate because MVC can do all this for you. Just change the model type to be @model CheckboxItem, remove the loop and get rid of the id attribute so it looks like this:

@model CheckboxItem
@{        

   <div>
   @Html.CheckBoxFor(x => x.Checked, new { onclick = "GetSelectedFrame()" })
      <span id="Padded">@Model.Text</span>
   </div> 
    }
}

Also, make sure your EditorFor call doesn't supply the EditorTemplate's name, as this messes up the "MVC Magic" (see this question which explains that it automatically iterates the list without the template name and doesn't with the template name):

@Html.BeginForm(){ 
    @Html.EditorFor(m=> m.FirstCheckboxList) 
    @Html.EditorFor(m=> m.SecondCheckboxList) 
} 
Community
  • 1
  • 1
theyetiman
  • 8,514
  • 2
  • 32
  • 41
  • _Thanks for your reply_ 1. Making List didn’t make any difference. 2. If I take For loop off how , then I will get below error right? The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[CheckboxItem]', but this dictionary requires a model item of type CheckboxItem – kum123 Apr 29 '13 at 15:55
  • I'm sorry the `List` suggestion didn't work. As for the second point, try changing the `EditorFor` call by removing the templatename: `@Html.BeginForm(){ @Html.EditorFor(m=> m.FirstCheckboxList) @Html.EditorFor(m=> m.SecondCheckboxList) }` – theyetiman Apr 29 '13 at 16:03
  • Can you show me the HTML that is generated? There is probably a problem with supplying the `id` to the checkbox instead of letting the model binder set its own – theyetiman Apr 29 '13 at 16:07
  • @kum123 - So are you objects still null when you POST? If they are now fixed please mark this as the answer. Also, that doesn't look like HTML, instead it looks like you've copy and pasted a value from the request object in the Visual Studio debugger. Please edit your question and include the HTML that is output to your web browser (press CTRL-U or right-click > View Source on the page). I will edit my answer to explain why `Html.EditorFor()` doesn't work when you supply the template name... – theyetiman Apr 30 '13 at 08:36
  • It worked as you explain, but I will be curious to know. Why it doesn't work, when you mention template name. Thanks for your help. – kum123 Apr 30 '13 at 09:26
  • @kum123 please see the question I have now linked in the answer: http://stackoverflow.com/questions/14038392/editorfor-ienumerablet-with-templatename To paraphrase @Darin Dimitrov: `The simple answer is it sucks badly, but that's how the designers of the framework decided to implement this feature.` – theyetiman Apr 30 '13 at 10:05