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

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

问题描述

我开始我的第一个ASP.NET MVC项目,所以我有一个简单的问题。
我有以下code:

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

在Model.GeneralQuestions所有问题都是独一无二的,所以单选按钮应该由name属性被分成组(每题一组单选按钮)。但是,这code只产生一组,所以当我回答第二个问题,第一个将变为取消。
我需要做什么改变?

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

在StudentViewModel的一个实例我救一个学生,他应该回答所有的问题(一般和相关科目,他正在研究),并通过它来查看。鉴于我把单一形式的所有问题,而且都是类型电台。因此,谁能帮助我与单选按钮组并正确回发这种形式?

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?

推荐答案

有一些与你的code,包括产生重复的问题 ID 的(无效HTML),生成重复名称属性(这就是为什么你只创建一个组,但更重要的是会绑定到这些模型时,你回发prevent你)和你实际上并不绑定到一个有效的财产反正。您将需要创建视图模型在循环再present你想要什么来显示和编辑,并生成单选按钮(或使用 EditorTemplate ),因此它们能够被正确使用索引名为

There are a number of problems with your code including generating duplicate id's (invalid html), generating duplicate name attributes (which is why your creating only one group, but more importantly will prevent you from binding to the model when you post back) and you 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

查看模型

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 SubjectID 空值>将其标识为一般的问题)。我建议你​​只是在GET方法硬编码一些值开始看到它是如何工作的,并会回

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

当您发布,模型填充在每个主题每个问题选择答案的ID。注意某些属性使用 DisplayFor()的。这些不会回来后,所以你需要,如果你回到视图重新填充这些属性(例如的ModelState 无效)。或者您可以生成一个文本框只读或添加一个隐藏的输入这些属性。我也建议你检查所生成的HTML,尤其是name属性,这将是这个样子

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 wont 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 readonly 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆