Asp.net mvc MVC和数据绑定到模型的子选择

Asp.net mvc MVC和数据绑定到模型的子选择,asp.net-mvc,data-binding,razor,Asp.net Mvc,Data Binding,Razor,我想将视图绑定到自定义模型的集合。这应该不会有任何问题,如果我使用generel方法来实现这一点,从我的视图循环遍历模型项,并在声明模型时使用括号语法: 即: 我的问题是我需要对我的模型项进行一些分组,因此我对我的项进行了子选择: @foreach(var itemType in Model.GroupBy(item => item.Type).Select(grp => grp.First())) { <p>@itemType:</p> v

我想将视图绑定到自定义模型的集合。这应该不会有任何问题,如果我使用generel方法来实现这一点,从我的视图循环遍历模型项,并在声明模型时使用括号语法:

即:

我的问题是我需要对我的模型项进行一些分组,因此我对我的项进行了子选择:

@foreach(var itemType in Model.GroupBy(item => item.Type).Select(grp => grp.First()))
{
    <p>@itemType:</p>

    var selection = Model
        .Where(p => p.Type == itemType)
        .OrderBy(p => p.CreationDate);

    for (int i = 0; i < selection.Count(); i++) {
       @Html.HiddenFor(m => selection[i].Id)
       @* all my other element bindings here... *@
       ...
    }
@foreach(Model.GroupBy中的var itemType(item=>item.Type)。选择(grp=>grp.First())
{
@项目类型:

var选择=模型 .Where(p=>p.Type==itemType) .OrderBy(p=>p.CreationDate); 对于(int i=0;iselection[i].Id) @*我的所有其他元素绑定都在这里*@ ... }

现在的问题是,我的控制器方法收到提交的表单后,得到了一个空模型。因此,模型的序列化在某个点上被破坏了;也许MVC不喜欢我的“选择”变量名?。或者我的问题可能是什么,我如何解决它?

问题在于生成视图时为每个项目生成的名称。模型绑定器使用名称-值对来确定如何将表单值映射到控制器中所需的视图模型

当您使用
@Html.HiddenFor(m=>m[i].Id)
时,这很好,会在Html中生成以下name属性:

name="[0].ModelId"
晚一点的是

name="[5].ModelId"
等等

以下是使用视图生成的HTML:

这里有两个问题:

  • 值“selection”出现在名称的前面
  • 它使用0作为数组索引的两倍
  • 这是因为所有带有for的HTML标记在最后的工作方式(HiddenFor、TextboxFor等)。它们基于lambda表达式确定name属性-因为您使用的是
    m=>m[0]。ModelId
    在第一个中使用
    [0]。ModelId
    作为名称。在第二个中,您使用
    m=>selection[0].ModelId
    ,因此它使用了
    选择[i].ModelId
    (它删除了用作lambda一部分的任何变量

    那么,你如何解决这个问题

    给定当前设置,您可以通过以下两种方法之一实现此目的。您可以在循环外部使用计数器并将其用作数组索引,或者您可以利用使用额外的隐藏字段作为索引字段的优势。对于任何一种方法,您都必须删除强类型的HiddenFor/TextBoxFor,而改用HiddenFor/TextBox手动设置正在生成的HTML元素的名称

    索引字段的情况是,项目名称如下所示:

    <input type="hidden" name="Index" value="Model1"/>
    <input type="hidden" name="[Model1].ModelId" value="1"/>
    <input type="hidden" name="[Model1].ModelValue" value="Some value"/>
    
    
    
    在第一个输入标记上,我将其称为index,并设置一些值作为这组相关值的索引。在其余的输入标记上,我使用值集作为第一个输入标记中的值作为数组索引,然后只是属性的名称。如果您在添加/r正在从列表中删除项目,但不能保证在发回时将按顺序显示所有数字

    这就是Razor代码的样子:

    for (int i = 0; i < selection.Count(); i++) {
        @Html.Hidden("Index", "Model"+selection[i].ModelId)
        @Html.Hidden("[Model"+selection[i].ModelId + "].ModelId", selection[i].ModelId)
        @Html.Hidden("[Model"+selection[i].ModelId + "].CreateDate", selection[i].CreateDate)
        @Html.Hidden("[Model"+selection[i].ModelId + "].ModelValue", selection[i].ModelValue)
    
    for(int i=0;i
    作为旁注,我选择加入“Model”一词作为索引的一部分,它肯定知道它是将其引用为类似字典的条目,而不是数组中的数字位置。我不知道您是否绝对需要这样做,我实际上没有尝试其他方法。我使用ModelId作为索引值,因为这应该是唯一的值

    最终结果是您应该生成如下所示的HTML(就名称属性而言):


    希望这会有所帮助!

    您试图绑定到的视图模型是什么样子的(在接收提交的控制器方法中)?它只是一个集合,而您只是尝试返回原始集合的子集吗?我的视图模型只是一个简单POCO类的集合。然后,我的视图可以编辑集合中的项。因此,我不想减少原始集合。子集“选择”只是迭代我的视图中每个组的子集项集合。我更感兴趣的是项目的命名,但我可能有足够的时间继续,而不是在视图中进行分组。在操作方法中进行分组
    for (int i = 0; i < selection.Count(); i++) {
        @Html.Hidden("Index", "Model"+selection[i].ModelId)
        @Html.Hidden("[Model"+selection[i].ModelId + "].ModelId", selection[i].ModelId)
        @Html.Hidden("[Model"+selection[i].ModelId + "].CreateDate", selection[i].CreateDate)
        @Html.Hidden("[Model"+selection[i].ModelId + "].ModelValue", selection[i].ModelValue)