ASP.NET MVC 5组单选button
我开始我的第一个ASP.NET MVC项目,所以我有一个简单的问题。 我有以下代码:
foreach(var question in Model.GeneralQuestions) { <div class = "well"> <h3> <strong>@question.QuestionString</strong> </h3> @foreach (var answer in question.PossibleAnswers) { @Html.RadioButtonFor(model => question.QuestionString, answer.Answer) @Html.Label(answer.Answer) <br /> } </div> }
Model.GeneralQuestions中的所有问题都是唯一的,所以单选button应该按名称属性分组(每个单选button一组)。 但是这个代码只产生一个组,所以当我第一个回答第一个问题时就会被取消select。 我需要改变什么?
编辑
我的模型看起来像:
public class StudentViewModel { public Student Student { get; set; } public List<Question> GeneralQuestions { get; set; } public List<SubjectQuestions> SubjectQuestions { get; set; } } public class Student { public int StudentID { get; set; } public string Index { get; set; } public string Name { get; set; } public string Surname { get; set; } public virtual ICollection<Subject> Subjects { get; set; } } public class Question { public int QuestionID { get; set; } public string QuestionString { get; set; } public bool IsAssociatedWithSubject { get; set; } public virtual ICollection<PossibleAnswer> PossibleAnswers { get; set; } public virtual ICollection<Results> Results { get; set; } } public class SubjectQuestions { public Subject Subject { get; set; } public List<Question> Questions { get; set; } } public class Results { public int ResultsID { get; set; } public int QuestionID { get; set; } public int? SubjectID { get; set; } public int PossibleAnswerID { get; set; } public virtual Question Question { get; set; } public virtual PossibleAnswer PossibleAnswer { get; set; } public virtual Subject Subject { get; set; } }
在StudentViewModel的一个例子中,我保存一个学生和所有他应该回答的问题(包括一般的和他正在学习的科目相关的),并通过它来查看。 有鉴于此,我把所有的问题都以单一的forms提出,而且都是无线电的types。 那么,任何人都可以帮助我分组的单选button,并正确地张贴回来这种forms?
你的代码有很多问题,包括生成重复的id
(无效的html),生成重复的name
属性(这就是为什么你只创build一个组,但更重要的是,这将阻止你绑定到模型,当你回发),而且你实际上并没有绑定到一个有效的财产。
您将需要创build视图模型来表示要显示和编辑的内容,并在for
循环(或使用EditorTemplate
)中生成单选button,以便使用索引器正确命名它们。
查看模型
public class QuestionVM { public int ID { get; set; } // for binding public string Text { get; set; } [Required] public int? SelectedAnswer { get; set; } // for binding public IEnumerable<AnswerVM> PossibleAnswers { get; set; } } public class SubjectVM { public int? ID { get; set; } [DisplayFormat(NullDisplayText = "General")] public string Name { get; set; } public List<QuestionVM> Questions { get; set; } } public class AnswerVM { public int ID { get; set; } public string Text { get; set; } } public class StudentVM { public int ID { get; set; } public string Name { get; set; } // plus any other properties of student that you want to display in the view public List<SubjectVM> Subjects { get; set; } }
视图
@model YourAssembly.StudentVM @using(Html.BeginForm()) { @Html.HiddenFor(m => m.ID) @Html.DisplayFor(m => m.Name) for(int i = 0; i < Model.Subjects.Count; i++) { @Html.HiddenFor(m => m.Subjects[i].ID) @Html.DisplayFor(m => m.Subjects[i].Name) // will display "General" if no name for (int j = 0; j < Model.Subjects[i].Questions.Count; j++) { @Html.HiddenFor(m => m.Subjects[i].Questions[j].ID) @Html.DisplayFor(m => m.Subjects[i].Questions[j].Text) foreach(var answer in Model.Subjects[i].Questions[j].PossibleAnswers ) { <div> @Html.RadioButtonFor(m => m.Subjects[i].Questions[j].SelectedAnswer, answer.ID, new { id = answer.ID}) <label for="@answer.ID">@answer.Text</label> </div> } @Html.ValidationMessageFor(m => m.Subjects[i].Questions[j].SelectedAnswer) } } <input type="submit" value="save" /> }
调节器
public ActionResult Edit(int ID) { StudentVM model = new StudentVM(); // populate your view model with values from the database return View(model); } [HttpPost] public ActionResult Edit(StudentVM model) { // save and redirect }
注意我对你的模型所隐含的数据库结构有点困惑(例如,为什么当SubjectQuestion
为null
值将它标识为“常规”问题时,为什么需要单独的Question
和SubjectQuestion
模型)。 我build议你只是硬编码在GET方法的一些值,看看它是如何工作和职位回到开始。
StudentVM model = new StudentVM(); model.ID = 1; model.Name = "bambiinela"; model.Subjects = new List<SubjectVM>() { new SubjectVM() { Questions = new List<QuestionVM>() { new QuestionVM() { ID = 1, Text = "Question 1", SelectedAnswer = ?, // set this if you want to preselect an option PossibleAnswers = new List<AnswerVM>() { new AnswerVM() { ID = 1, Text = "Answer A" }, new AnswerVM() { ID = 1, Text = "Answer B" } } }, new QuestionVM() { ID = 2, Text = "Question 2", PossibleAnswers = new List<AnswerVM>() { // similar to above } } } }, new SubjectVM() { ID = 1, Name = "Math", Questions = new List<QuestionVM>() { // similar to above } } };
当您发布,该模型是填充在每个学科每个问题select的答案的ID。 注意一些属性使用DisplayFor()
。 这些将不会回发,所以如果您返回视图(例如ModelState
无效),您将需要重新填充这些属性。 另外,您可以生成一个只读的文本框或添加一个隐藏input这些属性。 我也build议你检查所生成的HTML,尤其是name属性,这将是这个样子
<input type="radio" name="Subjects[0].Questions[0].SelectedAnswer" ...
让您了解如何在收回后将集合绑定到您的模型
诀窍是使用一个expression式(Html.RadioButtonFor的第一个参数),其中包含一个值,每个单选button组都会改变一个值。 就你而言,这将是问题列表中的一个索引。
这是一些示例代码:
@for (int i = 0; i < Model.GeneralQuestions.Count; i++) { var question = Model.GeneralQuestions[i]; @Html.Label(question.QuestionString) <br /> foreach (var answer in question.PossibleAnswers) { @Html.RadioButtonFor(model => Model.GeneralQuestions[i].SelectedAnswerId, answer.Id) @Html.Label(answer.Answer) <br /> } }
这会产生以下HTML:
<label for="Q1">Q1</label> <br /> <input id="GeneralQuestions_0__SelectedAnswerId" name="GeneralQuestions[0].SelectedAnswerId" type="radio" value="1" /> <label for="A01">A01</label> <br /> <input id="GeneralQuestions_0__SelectedAnswerId" name="GeneralQuestions[0].SelectedAnswerId" type="radio" value="2" /> <label for="A02">A02</label> <br /> <label for="Q2">Q2</label> <br /> <input id="GeneralQuestions_1__SelectedAnswerId" name="GeneralQuestions[1].SelectedAnswerId" type="radio" value="11" /> <label for="A11">A11</label> <br /> <input id="GeneralQuestions_1__SelectedAnswerId" name="GeneralQuestions[1].SelectedAnswerId" type="radio" value="12" /> <label for="A12">A12</label> <br />
为了完整起见,下面是所使用模型的简化版本:
public class StudentViewModel { public List<Question> GeneralQuestions { get; set; } } public class Question { public int QuestionId { get; set; } public string QuestionString { get; set; } public ICollection<PossibleAnswer> PossibleAnswers { get; set; } public int SelectedAnswerId { get; set; } } public class PossibleAnswer { public int Id { get; set; } public string Answer { get; set; } }
这里是来自操作方法的代码:
return View(new StudentViewModel { GeneralQuestions = new List<Question> { new Question { QuestionString = "Q1", PossibleAnswers = new[] { new PossibleAnswer {Id = 1, Answer = "A01"}, new PossibleAnswer {Id = 2, Answer = "A02"} } }, new Question { QuestionString = "Q2", PossibleAnswers = new[] { new PossibleAnswer {Id = 11, Answer = "A11"}, new PossibleAnswer {Id = 12, Answer = "A12"} } }, } });