简体   繁体   中英

Nested for loops - RadioButtonFor not working

I have nested foreach loops in my view, and am having problems with the radio buttons.

@foreach (var header in Model.surveyHeaders)
{
    <h1>@header.Name</h1>

foreach (var subHeader in Model.surveySubHeaders.Where(x => x.SurveryHeaderID == header.ID))
{
<h2>@subHeader.Name</h2>

    foreach (var question in Model.surveyQuestions.Where(x => x.SurveySubHeaderID == subHeader.ID))
    {
        @Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 1);
        @Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 2);
        @Html.RadioButtonFor(x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value, 3);            
        @question.Question
    }
}

}

The radio button name is always 'Value', so the radio buttons are not grouped. What can I do to achieve the grouping that is desired?

Ah collections in MVC, the joy! In order to make sure all fields are named accordingly in order to be correctly model bound on post, you need to use for loops, that will set the indexes correctly.

Before doing so, you're going to have to tweak your model structure to save your headaches. You need to re-arrange your logic so that you have a hierarchical object model in which you can iterate more cleaner (this way we're getting away from logic in the view too!)

Your survey header class, can't you put a list of subheaders on it? Then your subheader class, can you put the list of questions for that subheader? That way you can do:

@for (var i = 0; i < Model.SurveyHeaders.Count; i++)
{
    <h1>@Model.SurveyHeaders[i].Name</h1>

    for (var j = 0; j < Model.SurveyHeaders[i].SubHeaders.Count; j++)
    {
        <h2>@Model.SurveyHeaders[i].SubHeaders[j].Name</h2>

        for (var k = 0; k < Model.SurveyHeaders[i].SubHeaders[j].Questions.Count; k++)
        {
            @Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 1);
            @Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 2);
            @Html.RadioButtonFor(x => x.SurveyHeaders[i].SubHeaders[j].Questions[k].Value , 3);            
            @Model.SurveyHeaders[i].SubHeaders[j].Questions[k].Question
        }
    }
}

This assumes your new model structure is something like (with the following classes):

public class MyModel
{
    public List<SurveyHeader> SurveyHeaders { get; set; }
}

public class SurveyHeader
{
    public string Name { get; set; }
    public List<SubHeader> SubHeaders { get; set; }
}

public class SubHeader
{
    public string Name { get; set; }
    public List<Question> Questions { get; set; }
}

public class Question
{
    public int Value { get; set; }
    public string Question { get; set; }
}

Also one other tip, for future reference, you use the following LINQ in your code:

x => x.surveyResults.Where(y => y.SurveyQuestionID == question.ID).First().Value

You can simplify it because First can actually take a lamba, like so (although you should use FirstOrDefault and null check it in future just for safety):

x => x.surveyResults.First(y => y.SurveyQuestionID == question.ID).Value

您可以使用接收HtmlAttributes的RadioButtonFor扩展的重载并设置每个RadioButton的名称。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM