我有这些模特。
ProjectViewModel
public class ProjectViewModel
{
//some properties..
public IList<ScopeOfWorkViewModel> ScopeOfWork { get; set; }
}
ScopeOfWorkViewModel
public class ScopeOfWorkViewModel
{
//some properties
public IList<MaterialsViewModel> Materials { get; set; }
}
MaterialsViewModel
public class MaterialsViewModel
{
public int MaterialId { get; set; }
[Display(Name = "Material")]
public string MaterialName { get; set; }
public int? Quantity { get; set; }
public double? Cost { get; set; }
public int? ScopeOfWorkId { get; set; }
// should be a drop down list and get its data from database
public IEnumerable<SelectListItem> CategoryList { get; set; }
}
类别模型
public partial class tblCategory
{
public tblCategory()
{
this.tblMaterials = new HashSet<tblMaterial>();
}
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<tblMaterial> tblMaterials { get; set; }
}
这是我的观点
@model MigratingDB.Models.ProjectViewModel
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal" id="ProjectForm">
<h4>ProjectViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
Dynamically add ScopeOfWork and Materials<br />
<a href="javascript:void(0)" id="addScope">Add Scope of Work</a>
<div id="scopes">
<div class="scope">
<div class="materials">
<div class="material">
</div>
</div>
</div>
</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>
<div id="newScope" style="display:none">
<div class="scope">
<h3>Scope</h3>
<div class="form-group">
<label for="_#__ScopeOfWorkName" class="control-label col-md-2">Scope Of Work</label>
<div class="col-md-10">
<input class="form-control" type="text" id="_#__ScopeOfWorkName" name="ScopeOfWork[#].ScopeOfWorkName" value="">
</div>
</div>
<input type="hidden" class="scopeindex" name="ScopeOfWork.Index" value="#" />
<div class="materials">
<h4>Material</h4>
<a href="javascript:void(0)" class="addmaterial">Add Material</a>
</div>
</div>
</div>
<div id="newMaterial" style="display:none">
<div class="form-group">
<label for="_#__Materials_%__MaterialName" class="control-label col-md-2">Material</label>
<div class="col-md-2">
<input class="form-control" type="text" id="_#__Materials_%__MaterialName" name="ScopeOfWork[#].Materials[%].MaterialName" value="">
</div>
</div>
<div class="form-group">
<label for="_#__Materials_%__Quantity" class="control-label col-md-2">Quantity</label>
<div class="col-md-1">
<input class="form-control" type="text" id="_#__Materials_%__Quantity" name="ScopeOfWork[#].Materials[%].Quantity" value="">
</div>
</div>
<div class="form-group">
<label for="_#__Materials_%__Cost" class="control-label col-md-2">Cost</label>
<div class="col-md-1">
<input class="form-control" type="text" id="_#__Materials_%__Cost" name="ScopeOfWork[#].Materials[%].Cost" value="">
</div>
</div>
//build a category drop down list here
<input type="hidden" class="materialindex" name="ScopeOfWork[#].Materials.Index" value="%" />
</div>
<script>
var form = $('form');
var scope = $('#newScope');
var material = $('#newMaterial');
form.on('click', '.addmaterial', function () {
var clone = material.clone();
var scopeIndex = $(this).closest('.scope').find('.scopeindex').val();
clone.html($(clone).html().replace(/#/g, scopeIndex));
var materialIndex = new Date().getTime();
clone.html($(clone).html().replace(/%/g, materialIndex));
$(this).closest('.materials').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
$('#addScope').click(function () {
var clone = scope.clone();
var scopeIndex = new Date().getTime();
clone.html($(clone).html().replace(/#/g, scopeIndex));
$('#scopes').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
</script>
请在每次创建MaterialViewModel对象并将其发布到我的数据库时帮助我为该类别构建一个下拉列表。我有一个类别表,我想在其中传递其值以生成下拉列表。我更喜欢使用强类型模型而不是使用ViewBag
答案 0 :(得分:0)
您的ProjectViewModel
需要一个属性IEnumerable<SelectListItem>
(或包含2个属性的类IEnumerable
作为选项值和文本),以便您可以将选项值传递给视图(如果没有MaterialsViewModel
)。您的MaterialsViewModel
还需要一个属性来将所选类别绑定到。
public class ProjectViewModel
{
// some properties..
public IEnumerable<SelectListItem> CategoryList { get; set; }
public IList<ScopeOfWorkViewModel> ScopeOfWork { get; set; }
}
....
public class MaterialsViewModel
{
public int MaterialId { get; set; }
....
// public int? ScopeOfWorkId { get; set; } this is not required
public int SelectedCategory { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
}
然后在GET方法中,初始化视图模型并填充CategoryList
,例如
IEnumerable categories = db.tblCategory; // select all categories
ProjectViewModel model = new ProjectViewModel()
{
CategoryList = new SelectList(categories, "CategoryId", "CategoryName"),
.... set other properties as required
};
return View(model);
在视图中,包含一个脚本,用于将CategoryList
转换为javascript数组
<script>
var form = $('form');
....
var categories = @Html.Raw(Json.Encode(Model.CategoryList));
form.on('click', '.addmaterial', function () {
....
然后在你的模板中(在`元素中),为select控件添加html(但是如果你需要的话,除了label选项之外没有任何选项)。请注意选择的附加类名。
<div class="form-group">
<label for="_#__Materials_%__SelectedCategory" class="control-label col-md-2">Cost</label>
<div class="col-md-1">
<select class="form-control category" id="_#__Materials_%__SelectedCategory" name="ScopeOfWork[#].Materials[%].SelectedCategory">
<option value="">Please select a category</option>
</select>
</div>
</div>
并修改脚本以根据javascript数组中的值添加选项。
form.on('click', '.addmaterial', function () {
var clone = material.clone();
....
clone.html($(clone).html().replace(/%/g, materialIndex));
// Add the options
var select = clone.find('.category');
$.each(categories, function(index, item) {
select.append($('<option></option>').val(item.Value).text(item.Text));
});
$(this).closest('.materials').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
请注意,您没有为现有项呈现任何html,因此如果任何内容无效并且您返回视图,则用户动态添加的所有数据都将丢失 - 您需要嵌套for
循环。而且你没有在动态添加的元素上渲染html进行验证。