在ASP.NET MVC中将集合传递给EditorFor

Adi*_*lil 9 asp.net asp.net-mvc editorfor razor

我有一个冗长的形式,我已经破解了几个部分,并使用@ Html.EditorFor为每个部分工作得很好,但需要你的想法是否可以改进这种方法.

有段和每个段可以有多个活动,所以我有一个段的集合,此集合中的每个段包含一个活动集合.

    public class Activity
    {
        public string ActivityId { get; set; }
        public string ActivityDescription { get; set; }
        public bool IsSelected { get; set; }
    }
    public class Segment
    {
        public string SegmentId { get; set; }
        public string SegmentDescription { get; set; }
        public List<Activity> Activitites { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

这就是我希望我用作视图模型的ViewModel看起来如何,但由于@ Html.EditorFor不接受集合类型而无法使其工作.

    public class UserPreferencesViewModel
   {
       //..... Other Properties
       public List<Segment> Segments {get; set;}
   }
Run Code Online (Sandbox Code Playgroud)

这是ViewModel

@model UserPreferencesViewModel
@{
   //... Other Properties
   @Html.EditorFor(m => m.Segments) //I assigned Segments three Segments in the Controller Get Method
}
Run Code Online (Sandbox Code Playgroud)

这是EditorFor Template for Segments

@model List<Segment>
@{
   //... Other Properties
   @foreach(var segment in Model)
   {
      //Do the stuff
   }
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用,说EditorFor无法获取集合,并且在RunTime中抛出异常.

这是我的工作.我创建了另一个类"UglySegmentWorkAround",其中包含Segment Collection,然后在UserPreferencesViewModel中我删除了List Property,而是为其定义了一个属性.

public class UglySegmentWorkAround
{
public List<Segment> Segments {get; set;}
}

public class UserPreferencesViewModel
       {
           //..... Other Properties
           public UglySegmentWorkAround UglySegmentWorkAround {get; set;}
       }
Run Code Online (Sandbox Code Playgroud)

这是EditorFor Template.

@model UglySegmentWorkAround
    @{
       //... Other Properties
       @foreach(var segments in Model.Segments)
       {
          //Do the stuff
       }
    }
Run Code Online (Sandbox Code Playgroud)

它工作得很完美,但我对这种方法感到不舒服,第一种方法中有什么我缺少的吗?应该怎么做?如果我将它传递给集合,我不希望EditorFor执行隐式循环,因为我在EditorFor中渲染复杂的UI结构,我需要EditorFor在其中包含循环.

Eri*_*sch 29

EditorFor旨在为您迭代集合.它会自动执行此操作.将集合传递给EditorFor时,它会自动为集合中的每个项目调用模板.

如果您需要为整个集合设置一些渲染,那么您应该在EditorFor调用之外,在视图代码中或在调用EditorFor的局部视图中执行此操作.

例如,如果你想把你的代码放在一个表中,你会这样做(MyCollection所在的地方List<MyItem>):

_MyCollectionPartial.cshtml

<table>
    <tr>
       <th>Foo...</th>
       ...
     <tr>
     @Html.EditorFor(x => x.MyCollection)
</table>
Run Code Online (Sandbox Code Playgroud)

/Views/Shared/EditorTemplates/MyItem.cshtml

@model MyItem
<tr>
    <td>@Html.TextBox(x => x.Foo)</td>
    ....
</tr>
Run Code Online (Sandbox Code Playgroud)

编辑:

也许更好的方法是使用编辑器模板的一个鲜为人知且记录不完整的"特征".而"特征"是指如果您将模板名称指定为参数,则它不会迭代集合.您可以使用此表单"包装"您的收藏项模板.

/Home/Index.cshtml

.... your html
@Html.EditorFor(model => model.MyCollection, "MyCollectionLayout")
Run Code Online (Sandbox Code Playgroud)

/Views/Shared/EditorTemplates/MyCollectionLayout.cshtml

@model List<MyItem>
<table>
    <tr>
       <th>Foo...</th>
       ...
     <tr>
     @Html.EditorForModel() (Or alternatively @Html.EditorFor(model => model)
 </table>
Run Code Online (Sandbox Code Playgroud)

/Views/Shared/EditorTemplates/MyItem.cshtml

@model MyItem
<tr>
    <td>@Html.TextBoxFor(x => x.Foo)</td>
    ....
</tr>
Run Code Online (Sandbox Code Playgroud)

注意:我说"功能",因为这在SO上产生了很多问题,关于它在参数中明确指定模板名称时不迭代集合)

  • "那个"功能"是指如果你指定一个模板名称作为参数,那么它就不会迭代这个集合"非常感谢你. (4认同)