Using partial views for each question type wont work easily because by default they will not prefix the form controls name
attribute with the collections indexer necessary for binding when you post and you will need multiple conditional statements to determine which partial to display.
Assuming its acceptable to group the questions in the view according to their type, then using custom EditorTemplate
's for each type or for
loop. A basic model structure might be
public enum QuestionType
{
YesNo,
Text,
MultipleChoice
}
public class Survey
{
public int ID { get; set; }
public string Title { get; set; }
public List<YesNoQuestion> YesNoQuestions { get; set; }
public List<TextQuestion> TextQuestions { get; set; }
public List<MultipleChoiceQuestion> MultipleChoiceQuestions { get; set; }
}
public abstract class Question
{
public int ID { get; set; }
public string Text { get; set; }
public QuestionType Type { get; set; }
}
public class YesNoQuestion : Question
{
public bool Answer { get; set; }
}
public class TextQuestion : Question
{
public string Answer { get; set; }
}
public class MultipleChoiceQuestion : Question
{
public int Answer { get; set; }
public List<MultipleChoiceAnswer> PossibleAnswers { get; set; }
}
public class MultipleChoiceAnswer
{
public int ID { get; set; }
public int QuestionID { get; set; }
public string Text { get; set; }
}
and a simplified view (using for
loops)
@model yourAssembly.Survey
@using (Html.BeginForm())
{
<h2>@Html.DisplayFor(m => m.Title)</h2>
<h3>Yes/No questions</h3>
for(int i = 0; i < Model.YesNoQuestions.Count; i++)
{
<div>
@Html.CheckBoxFor(m => m.YesNoQuestions[i].Answer)
@Html.LabelFor(m => m.YesNoQuestions[i].Answer, Model.YesNoQuestions[i].Text)
</div>
}
<h3>Text questions</h3>
for(int i = 0; i < Model.TextQuestions.Count; i++)
{
@Html.LabelFor(m => m.TextQuestions[i].Answer, Model.TextQuestions[i].Text)
@Html.TextAreaFor(m => m.TextQuestions[i].Answer)
}
<h3>Multiple choice questions</h3>
for(int i = 0; i < Model.MultipleChoiceQuestions.Count; i++)
{
<div>@Html.DisplayFor(m => m.MultipleChoiceQuestions[i].Text)</div>
foreach(var option in Model.MultipleChoiceQuestions[i].PossibleAnswers)
{
var id = string.Format("option-{0}", option.ID);
<div>
@Html.RadioButtonFor(m => m.MultipleChoiceQuestions[i].Answer, option.ID, new { id = id })
<label for="@id">@option.Text</label>
</div>
}
}
<input type="submit" value="Save" />
}