2015-10-13 108 views
1

我发布了一个类似于这个的问题,但我不相信它正确地说明了我的问题。所以这里有更好的解释!将模型发回到包含复杂集合的控制器

我正在研究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以来未发生任何更改。

对不起,如果这一切看起来很复杂,它是和像我这样的初中,我认为最好的问我周围,因为我从来没有向控制器发布过列表和东西。

如果能提供帮助,我很乐意提供更多信息!

向那,

+0

不能使用'foreach'环或'的ElementAt(我)'生成将绑定到集合表单控件去。您生成的'name'属性没有与您的模型没有任何关系的索引器。你需要实现'IList ',你需要使用嵌套'for'循环(或者为你的类型使用自定义EditorTemplates –

回答

1

如果你改变你的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

+0

感谢你的所有建议。我已经走了编辑器模板路线,很高兴地宣布我的模型现在拥有我需要的一切!你是先生,是英雄! –

相关问题