ASP.NET MVC 5 单选按钮组 [英] ASP.NET MVC 5 group of radio buttons

查看:30
本文介绍了ASP.NET MVC 5 单选按钮组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开始我的第一个 ASP.NET MVC 项目,所以我有一个简单的问题.我有以下代码:

foreach(Model.GeneralQuestions 中的 var 问题){<div class = "well"><h3><strong>@question.QuestionString</strong>@foreach (var answer in question.PossibleAnswers){@Html.RadioButtonFor(model => question.QuestionString, answer.Answer)@Html.Label(answer.Answer)<br/>}

}

Model.GeneralQuestions 中的所有问题都是唯一的,因此应按名称属性将单选按钮分组(对于每个问题一组单选按钮).但是这段代码只产生一个组,所以当我回答第二个问题时,第一个被取消选择.我需要改变什么?

编辑
我的模型看起来像:

公共类StudentViewModel{公共学生学生{得到;放;}公共列表<问题>一般问题{得到;放;}公共列表<主题问题>主题问题{得到;放;}}公开课学生{公共 int StudentID { 获取;放;}公共字符串索引{获取;放;}公共字符串名称 { 获取;放;}公共字符串姓氏 { 获取;放;}公共虚拟 ICollection<主题>科目{得到;放;}}公开课问题{公共 int QuestionID { 获取;放;}公共字符串 QuestionString { get;放;}public bool IsAssociatedWithSubject { 获取;放;}公共虚拟 ICollection可能的答案{得到;放;}公共虚拟 ICollection<Results>结果{得到;放;}}公开课主题问题{公共主题主题{获取;放;}公共列表<问题>问题{得到;放;}}公开课成绩{公共 int 结果 ID { 获取;放;}公共 int QuestionID { 获取;放;}公众号?主题 ID { 获取;放;}public int可能的答案ID {得到;放;}公共虚拟问题 问题 { get;放;}公共虚拟可能的答案可能的答案{得到;放;}公共虚拟主题主题{获取;放;}}

在 StudentViewModel 的一个实例中,我保存了一名学生和他应该回答的所有问题(包括一般问题和与他正在学习的科目相关的问题)并将其传递给查看.鉴于我将所有问题都放在单一形式中,它们都是广播类型.那么,任何人都可以帮助我对单选按钮进行分组并正确发回此表单吗?

解决方案

您的代码存在许多问题,包括生成重复的 id(无效 html)、生成重复的 name 属性(这就是您只创建一个组的原因,但更重要的是,这将阻止您在回发时绑定到模型)并且您实际上并没有绑定到有效的属性.

您需要创建视图模型来表示要显示和编辑的内容,并在 for 循环(或使用 EditorTemplate)中生成单选按钮,以便它们使用索引器正确命名.

查看模型

公共类 QuestionVM{公共 int ID { 获取;放;}//用于绑定公共字符串文本 { 获取;放;}[必需的]公众号?SelectedAnswer { 得到;放;}//用于绑定公共 IEnumerable可能的答案{得到;放;}}公共类 SubjectVM{公众号?身份证{得到;放;}[DisplayFormat(NullDisplayText = "General")]公共字符串名称 { 获取;放;}公共列表问题{得到;放;}}公开课 AnswerVM{公共 int ID { 获取;放;}公共字符串文本 { 获取;放;}}公开课 StudentVM{公共 int ID { 获取;放;}公共字符串名称 { 获取;放;}//加上你想在视图中显示的学生的任何其他属性公共列表<SubjectVM>科目{得到;放;}}

查看

@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)//如果没有名字,将显示General"for (int j = 0; j  m.Subjects[i].Questions[j].ID)@Html.DisplayFor(m => m.Subjects[i].Questions[j].Text)foreach(模型中的var answer.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>

}@Html.ValidationMessageFor(m => m.Subjects[i].Questions[j].SelectedAnswer)}}<input type="submit" value="save"/>}

控制器

public ActionResult Edit(int ID){StudentVM 模型 = new StudentVM();//用数据库中的值填充你的视图模型返回视图(模型);}[HttpPost]公共 ActionResult 编辑(StudentVM 模型){//保存并重定向}

注意我对你的模型隐含的数据库结构有点困惑(例如,为什么你需要为 QuestionSubjectQuestion 单独的模型SubjectID 的 值将其标识为常规"问题).我建议您首先在 GET 方法中硬编码一些值,看看它是如何工作的并回传.

StudentVM 模型 = new StudentVM();型号.ID = 1;model.Name = "bambiinela";model.Subjects = new List(){新主题VM(){Questions = new List(){新问题VM(){ID = 1,Text = "问题 1",SelectedAnswer = ?,//如果要预选一个选项,请设置此项可能的答案 = 新列表(){新的答案VM(){ID = 1,文字 = "答案 A"},新的答案VM(){ID = 1,文字 = "答案 B"}}},新问题VM(){ID = 2,Text = "问题 2",可能的答案 = 新列表(){//类似上面}}}},新主题VM(){ID = 1,Name = "数学",Questions = new List(){//类似上面}}};

当您发帖时,模型中会填充每个主题中每个问题的所选答案的 ID.请注意对某些属性使用 DisplayFor().这些不会回传,因此如果您返回视图(例如 ModelState 无效),则需要重新填充这些属性.或者,您可以生成只读文本框或为这些属性添加隐藏输入.我还建议您检查生成的 HTML,特别是名称属性,它看起来像

<input type="radio" name="Subjects[0].Questions[0].SelectedAnswer" ...

让您了解集合如何在回发时绑定到您的模型

I am starting my first ASP.NET MVC project, so I have one simple question. I have following code:

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>
}

All questions in Model.GeneralQuestions are unique, so radio buttons should be divided into groups by name attribute (for each question one group of radio buttons). But this code produces only one group, so when I answer second question first one becomes deselected. What do I need to change?

EDIT
My model looks like:

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; }
}

In one instance of StudentViewModel I save one student and all questions that he should answer (both general and related to subjects he is studying) and pass it to view. In view I put all questions in single form and they are all type of radio. So, can anyone help me with grouping of radio buttons and posting back this form correctly?

解决方案

There are a number of problems with your code including generating duplicate id's (invalid html), generating duplicate name attributes (which is why you're creating only one group, but more importantly this will prevent you from binding to the model when you post back) and you're not actually binding to a valid property anyway.

You will need to create view models to represent what you want to display and edit and generate the radio buttons in a for loop (or using an EditorTemplate) so they are correctly named with indexers.

View models

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; }
}

View

@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" />
}

Controller

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
}

Note I am a little confused by the database structure implied by your models (for example why do you need separate models for Question and SubjectQuestion when a null value for SubjectID identifies it as a "General" question). I suggest you start by just hard-coding some values in the GET method to see how it works and posts back.

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
    }
  }
};

When you post, the model is populated with the ID of the selected answer for each question in each subject. Note the use of DisplayFor() for some properties. These won't post back so you would need to repopulate these properties if you return the view (e.g. ModelState is not valid). Alternatively you can generate a read-only textbox or add a hidden input for those properties. I also suggest you inspect the HTML that is generated, in particular the name attributes which will look something like

<input type="radio" name="Subjects[0].Questions[0].SelectedAnswer" ...

to give you an understanding of how collections are bound to your model on post back

这篇关于ASP.NET MVC 5 单选按钮组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆