【问题标题】:View Models and Check Boxes in View在视图中查看模型和复选框
【发布时间】:2012-10-19 18:54:57
【问题描述】:

我有一个新手问题,过去几天我一直在努力理解。希望有人可以帮助我理解编程流程。

假设我有一个模型,信息存储在数据库中:

public class Student
{
    public int studentID { get; set; }
    public string studentName { get; set; }
    public strin studentGrade {get; set; }
}

public class StudentDBContext : DbContext
{
    public DbSet<Student> Students { get; set; }
}

我想将它显示到视图中,并带有额外的复选框,以便我可以选择要提升到下一年级的学生。我读到这样做的一种方法是放入视图模型:

public class StudentViewModel
{
    public bool promoted { get; set; }
    public Student stu { get; set; }
}

但我被困住了,这是这样做的吗?如果是,您如何将其放入显示所有学生的视图中,旁边有一个复选框。之后,我想更新勾选复选框的学生的所有成绩。例如:

学生 A、学生 B、学生 D 从 1 年级提升到 2 年级。所以我想显示学生,勾选学生 A、B 和 D 并提交以更新成绩。

将不胜感激分步示例。

更新 1:

控制器:

    [HttpGet]
    public ViewResult CheckBox()
    {
        var studentViewModels = db.Students.Select(m => new StudentViewModel()
        {
            stu = m
        }).ToList();

        return View(studentViewModels);
    }

    [HttpPost]
    public ActionResult CheckBox(IList<studentViewModel> list)
    {

        foreach (var stuUpdate in list.Where(m => m.promoted))
        {
            var stuRow = db.Students.Find(stuUpdate.stu.studentID);
            stuRow.studentName = stuRow.studentName + "1";
            db.Entry(stuRow).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("CheckBox");
        }
        return RedirectToAction("CheckBox");
    }

查看:

@model IList<School.ViewModels.StudentViewModel>

@using (Html.BeginForm())
{
<table>
<tr>
    <th>

    </th>
    <th>
        student ID
    </th>
    <th>
        student name
    </th>
    <th>
        student grade
    </th>
</tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.CheckBoxFor(modelItem => item.promoted)
            @Html.HiddenFor(modelItem => item.stu.studentID)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.stu.studentID)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.stu.studentName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.stu.studentGrade)
        </td>
    </tr>
}

</table>
<input type="submit" value="save" />
}

但是目前遇到以下错误: 值不能为空。 参数名称:来源

Source Error:
foreach (var stuUpdate in list.Where(m => m.promoted))

【问题讨论】:

    标签: asp.net-mvc checkbox viewmodel


    【解决方案1】:

    一个非常基本的“逐步”(在 SO 中完成,所以我可能犯了一些错误,但你明白了)。

    你总是有几种方法来做这些事情,所以......只是把它作为一个样本,并找到其他例子来获得其他想法。

    首先,在您的控制器中,您将有一个 GET 操作(查看列表)。

    [HttpGet]
    public ViewResult StudentList() {
       //retrieve all students. With the Select, we create a new instance of StudentViewModel for each student.
      //assuming StudentDbContext being a property of your controller, if it's not, you can instantiate a new one (in a using clause)
       var studentViewModels = StudentDbContext.Students
                  .Select(m => new StudentViewModel() {
                       stu = m 
                      //we don't say nothing about promoted : 
                      //it will be there as "false" by default, which is probably what we want.
                  }).ToList();
        //now we've got a list of StudentViewModel. This will be the model of our view
        return View(studentViewModels);
    
    }
    

    然后我们有一个视图,StudentList.cshtml

    在这个视图中,我们将显示一个表格,每个学生都有一行:studentId(在这种情况下隐藏)、姓名(仅显示)、成绩(仅显示)和一个复选框。

    我们需要一个 for 循环(不是 foreach)来获得良好的模型绑定。

    @model IList<StudentViewModel>
    
    @using (Html.BeginForm()) {
    <table>
      <tr>
         <th>Student name</th>
         <th>Student grade</th>
         <th>Promote</th>
      </tr>
      @for (var i = 0; i < Model.Count(); i++) {
       <tr>
          <td>@Html.HiddenFor(m => Model[i].Student.studentID)
              @Html.DisplayFor(m => Model[i].Student.studentName)
          </td>
          <td>@Html.DisplayFor(m => Model[i]Student.studentGrade)</td>
          <td>@Html.CheckBoxFor(m => Model[i].promoted)</td>
      </tr>
      }
    </table>
    <input type="submit" value="save" />
    }
    

    此表单将导致另一个 POST 操作(与 GET 操作同名,具体取决于您在 Html.BeginForm 中的内容)

    [HttpPost]
    public ActionResult StudentList(IList<StudentViewModel> list) {
        //we treat only the lines where checkbox has been checked
        foreach (var studentViewModel in list.Where(m => m.promoted) {
           var student = StudentDBContext.GetById(studentViewModel.Student.studentID);//get student entity instance from context
           student.studentGrade ="<new value>";
           StudentDBContext.SaveChanges();//save changes, you must have such a method somewhere.
        }
        return Action("StudentList");
    }
    

    小细节:

    尽量尊重一些真正基本的“常规”做法:例如在 c# 中,属性应以大写字母开头(如 StudentGrade、StudentName、Promoted 等)。

    【讨论】:

    • 感谢您的指导。但是我收到错误消息,说 POST 方法中的值不能为空。有什么我想念的吗?还要感谢您提供有关属性的指针。我实际上是在 MVC 上进行自学,是否有任何指南或教程可以帮助我学习它?
    • @blurryMVC 如果您的实际代码是您在问题中编辑的内容,请按照我的回答中指出的那样将您的 foreach 循环更改为 for 循环
    • 感谢您的善意建议,但对 post 方法进行了细微调整。最初它只会更新第一行,只有在我搬出“return Action("StudentList");”之后在 for 循环之外它会更新两者。我也可以知道为什么 foreach 在 for 循环工作时不起作用?我阅读了论坛,我认为 foreach 是替换 for 循环本身。是否有不应该使用foreach的特殊情况?
    • @blurryMVC 代替 foreach 在可编辑列表中:stackoverflow.com/questions/8894442/…。没错,我回来的太快了;)
    • 哇,感谢您的帮助和链接。我会试着消化它。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 2018-07-16
    • 2011-05-07
    • 1970-01-01
    • 2011-09-08
    • 2015-11-29
    相关资源
    最近更新 更多