如何接受mvc创建视图的对象列表

时间:2016-08-21 10:40:11

标签: c# asp.net-mvc razor

我有两个这样的模型类

    public class JobViewModel
    {
        public int Id { get; set; }
        public float Price { get; set; }
        public int JobSubCategoryId { get; set; }
        public string jobDescription { get; set; }
        public List<Machine> Machines  { get; set; }
        public int SpecialRequirementId { get; set; }
    }

    public class Machine
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Brand { get; set; }
    }

现在,当用户创建一个新的&#34; Job&#34;他必须能够创造多个&#34;机器&#34;用它。如何在创建视图中实现此功能?

1 个答案:

答案 0 :(得分:0)

除了斯蒂芬的方法,你可以相对简单地实现所有这些,而不需要部分视图。

首先,您应该稍微修改一下您的模型。添加到机器:

    // Foreign key 
    public int JobID { get; set; }

    // Navigation properties 
    public virtual Job Job{ get; set; }

作业模型,您尚未展示,但需要:

public class Job
{
    public int Id { get; set; }
    public float Price { get; set; }
    public int JobSubCategoryId { get; set; }
    public string JobDescription { get; set; }
    public int SpecialRequirementId { get; set; }
    public virtual List<Machine> Machines { get; set; }
}

这是我完整的JobViewModel:

public class JobViewModel
{
    public JobViewModel()
    {
        Machines = new List<Machine>();
    }
    public int Id { get; set; }
    public float Price { get; set; }
    public int JobSubCategoryId { get; set; }
    public string JobDescription { get; set; }
    public int SpecialRequirementId { get; set; }
    public List<Machine> Machines { get; set; }
    public string NewMachineBrand { get; set; }
    public string NewMachineType { get; set; }
    public string NewMachineName { get; set; }
    public void AddMachine()
    {
        Machine tmp = new Machine { Brand = NewMachineBrand, Type = NewMachineType, Name = NewMachineName };
        Machines.Add(tmp);
        NewMachineBrand = NewMachineType = NewMachineName = null;
    }
    public Job GetJob()
    {
        Job job = new Job();
        job.JobDescription = JobDescription;
        job.Price = Price;
        job.JobSubCategoryId = JobSubCategoryId;
        job.SpecialRequirementId = SpecialRequirementId;
        job.Machines = new List<Machine>();
        foreach (Machine m in Machines)
        {
            job.Machines.Add(m);
        }
        return job;
    }
}

在创建基于JobViewModel的创建视图时,您需要添加两个非默认的东西,首先是一个用于存放新机器的表,其次是依次添加每个机器的按钮。

我的完整create.cshtml视图如下所示:

@model JobMachinesMVC.Models.JobViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
<div class="form-horizontal">
    <h4>Job</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.JobSubCategoryId, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.JobSubCategoryId, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.JobSubCategoryId, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.JobDescription, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.JobDescription, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.JobDescription, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SpecialRequirementId, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.SpecialRequirementId, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.SpecialRequirementId, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.NewMachineBrand, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.NewMachineBrand, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.NewMachineBrand, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.NewMachineType, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.NewMachineType, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.NewMachineType, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.NewMachineName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.NewMachineName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.NewMachineName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
            <table>
                <thead>
                    <tr>
                        <th style="text-align:right">
                            @Html.DisplayNameFor(model => model.Machines.FirstOrDefault().Brand)
                        </th>
                        <th style="text-align:right">
                            @Html.DisplayNameFor(model => model.Machines.FirstOrDefault().Name)
                        </th>
                        <th style="text-align:right">
                            @Html.DisplayNameFor(model => model.Machines.FirstOrDefault().Type)
                        </th>
                    </tr>
                </thead>
                <tbody>
                @for (int i = 0; i < Model.Machines.Count; i++)
                {
                    <tr>
                            <td style="text-align:right">@Html.HiddenFor(m => m.Machines[i].Id)@Html.DisplayFor(m => m.Machines[i].Brand)@Html.HiddenFor(m => m.Machines[i].Brand)</td>
                            <td style="text-align:right">@Html.DisplayFor(m => m.Machines[i].Name)@Html.HiddenFor(m => m.Machines[i].Name)</td>
                            <td style="text-align:right">@Html.DisplayFor(m => m.Machines[i].Type)@Html.HiddenFor(m => m.Machines[i].Type)</td>
                        </tr>
                }
                </tbody>
            </table>
    </div>

    <div class="form-group">
            <input type="submit" value="Add Machine" name="addmachine" class="btn btn-default" />
    </div>


    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>

        @Html.ActionLink("Back to List", "Index")
    </div>

    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }

这里有几点需要注意。我总是在这样的子表中包含@ Html.HiddenFor,因为在回发到控制器时,@ Html.DisplayFor项可能会丢失。其次,在同一个View上有两个输入类型=“提交”。一个给出一个名称属性。这样控制器就可以区分两次点击。

我的控制器的相关行是:

    // GET: Jobs/Create
    public ActionResult Create()
    {
        JobViewModel job = new JobViewModel();
        return View(job);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(JobViewModel jobvm)
    {
        if (Request.Form["addmachine"] != null)
        {
            jobvm.AddMachine();
            ModelState.Remove("NewMachineName");
            ModelState.Remove("NewMachineType");
            ModelState.Remove("NewMachineBrand");
            return View(jobvm);
        }
        if (ModelState.IsValid)
        {
            Job job = jobvm.GetJob();
            db.Jobs.Add(job);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(jobvm);
    }

如果单击“addmachine”,则新计算机值将添加到“计算机列表”中,重置并重新显示表单。请注意,即使ViewModel将值设置为null,也需要设置ModelState,否则旧值将保留在视图中。如果单击“创建”,则会检查模型的ValidState,并保存作业。 Machine表怎么样?由于模型的设置如上所述,因此内部MVC知道它必须将值保存到Machine。

请注意,上图非常粗糙。除了“开箱即用”之外,我没有应用任何造型。你会想要整理一下(很多!),但我希望我能以一种方式给你一个良好的开端来解决这个问题。