将模型发回到包含复杂集合的控制器
我发布了一个类似于这个的问题,但我不相信它正确地说明了我的问题。所以这里有更好的解释!将模型发回到包含复杂集合的控制器
我正在研究C#MVC 5应用程序。我有一个页面动态列出模型的集合属性A。此集合中的每个项目都使用一些引导程序来显示/隐藏它自己的集合属性B。所以只是为了澄清:这个模型有一个对象集合,每个对象都有一个与它相关的对象集合。这些对象每个都有一个复选框,它们绑定到一个isChecked布尔值,可以用来选择/取消选择项目。检查收藏A中的物品的一个框,自动选择其集合的所有复选框B。因此,您或许可以看到,在收集项目上具有复选框的唯一目的是充当其关联集合B项目的全选。
我试图将整个模型传递给控制器在POST上,然后做它的东西,例如,抓住所有物品,但遇到一些问题。
E.g.
@foreach (var category in Model.Categories)
{
var headerId = category.Name;
var childCounter = 0;
@*some divs and headers here*@
@if (category.Items.Any())
{
@*lets give it the ability to check all of its associated items*@
@Html.CheckBoxFor(d => category.IsChecked, new {id = @headerId, onclick = String.Format("CheckUncheckChildren({0}, {1})", @headerId, category.MenuItems.Count)})
}
else
{
@Html.CheckBoxFor(d => category.IsChecked)
}
@*some other divs and headings*@
@if (category.MenuItems.Any())
{
@foreach (var item in dealItemCategory.MenuItems)
{
var childId = childCounter++ + "_" + headerId;
var serverId = item.Id;
@*some other divs and headings*@
@Html.CheckBoxFor(d => item.IsChecked, new {id = @childId})
}
}
}
在页面上低了下去,我有:
for (var i = 0; i < Model.Categories.Count(); i++)
{
var category = Model.Categories.ElementAt(i);
var headerId = category.Name;
@Html.HiddenFor(d => category, new {id = @headerId})
for (var j = 0; j < Model.Categories.ElementAt(i).Items.Count(); j++)
{
var item = Model.Categories.ElementAt(i).Items.ElementAt(j);
@Html.HiddenFor(d => item, new {id = j + "_" + @headerId})
}
}
在我的脑海里,我保留在页面上这些属性对于这个复杂的集合......(不,我的理解是100% )我已经为这些隐藏的字段强制使用了id,以便它们与复选框的ID相关联。也许不是最好的办法,但它只是我试图得到这个工作的最后一件事...
现在我这里有两个选择:
1)相信在上面的意思是,只要选中/取消选择复选框,与其关联的集合中的对象将获取其isChecked布尔值已更改的对象。然后,发回整个模型,并希望我能够遍历所有检查的项目,并做出令人敬畏的东西。
或
2)在模型中创建一个字符串属性来保存对象的这种复杂的集合的JSON表示。当页面POSTED时,将此JSON字符串更新为希望更新的复杂集合的状态,以使其某些项目被选中/取消选中。然后,POST将整个模型和服务器端返回,我会将这个单个对象反序列化为一个逻辑上等效的复杂集合,并从那里开始工作。 也就是说 我的模型变化将增加一个属性:
public string JsonCategories{ get; set; }
然后在视图我不得不启动回发:
@Html.HiddenFor(d => d.JsonCategories);
function accept() {
var categories= @Html.Raw(Json.Encode(Model.Categories));
var jsonCategories = JSON.stringify(categories);
var a = $('#JsonCategories').val();
$('#JsonCategories').val(jsonCategories);
$("form").submit();
};
试图解决一个,我要么得到一个空对于Categories属性,或者如果我添加@ Html.HiddenFor(d => d.Categories);我得到一个空对象,计数为0。
试图溶液B,我得到了复杂的分类早在服务器土地可爱的JSON表示,但我看到的复选框选中我不改变的bool器isChecked导致我相信,而JSON对象能够在POST客户端上设置为Categories对象,因此用户完成的所有操作都不会保留,因此最终该模型的Categories集合从最初传递给View以来未发生任何更改。
对不起,如果这一切看起来很复杂,它是和像我这样的初中,我认为最好的问我周围,因为我从来没有向控制器发布过列表和东西。
如果能提供帮助,我很乐意提供更多信息!
向那,
如果你改变你的foreach循环,为循环您可以使用循环索引的lambda表达式。这应该使引擎输出发布值的正确语法。例如:
@for (int i = 0; i < Model.Categories.Count(); i++)
{
...
@Html.CheckBoxFor(d => d.Categories[i].IsChecked)
...
}
这应该正确地将值绑定到POST请求。生成的HTML将类似于下面的代码片段(0是第一项,1是第二等):
<input name="Categories[0].IsChecked" ... ></input>
另外,您可以为您的孩子打造集编辑模板,这将导致你写出这个片段来取代你的for循环当前的位置。
@Html.EditorFor(m => m.Categories)
更多关于如何做到这一点here。
这应该帮助你选择1
感谢你的所有建议。我已经走了编辑器模板路线,很高兴地宣布我的模型现在拥有我需要的一切!你是先生,是英雄! –
不能使用'foreach'环或'的ElementAt(我)'生成将绑定到集合表单控件去。您生成的'name'属性没有与您的模型没有任何关系的索引器。你需要实现'IList',你需要使用嵌套'for'循环(或者为你的类型使用自定义EditorTemplates –