我有两个这样的模型类
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;用它。如何在创建视图中实现此功能?
答案 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。
请注意,上图非常粗糙。除了“开箱即用”之外,我没有应用任何造型。你会想要整理一下(很多!),但我希望我能以一种方式给你一个良好的开端来解决这个问题。