为包含复杂对象列表的复杂对象制作编辑器表单

时间:2019-08-24 02:57:59

标签: c# razor model-view-controller

我正在一个MVC项目中,尝试在提交给数据库之前查看控制器已处理的复杂对象列表。对这个问题至关重要的是两个组成部分。

首先,该视图显示每个对象并带有一个复选框,以“保留此对象”(即:该对象适合添加)

第二,复杂对象全部来自一个源-但是每个复杂对象列表可以有多个源。我还需要为每个来源选择一个复选框,每个来源仅显示一次,表示不同的标志(不保留,但如果来源是完整的或仅是部分的)

因为这是关于过程生成的地图,所以有两件事:

Map Tiles列表(复杂对象的列表)-如果我们保留要添加到数据库或忽略它的每个复选框,则都带有一个复选框。 地图标识符(源)-每个运行带有一个复选框,指示我们是否知道这些是该运行的所有图块,还是仅少数几个图块。

到目前为止,我如何解决此问题:

在我看来,当我不担心区分来源时,我使用了EditorForModel。这对于使复选框重新显示在帖子中非常有用

<form asp-controller="Process" asp-action="Keep" method="post">


    <input type="submit" value="Submit Data" id="btnSubmit" />
    <hr />

    @Html.EditorForModel()

    <input type="submit" value="Submit Data" id="btnSubmit" />
    <hr />
</form>

带有原始模型的模板,该模板只是地图的每个图块。这并没有区分地图-我只是将所有图块(无论它们来自什么地图)都在一个列表中传递给视图。效果很好,我的后期操作可以分离出不同的地图,分别处理每个地图及其图块。

该视图基本上是:

- Tile 1 CheckBox: Keep[]?
- Tile 2 CheckBox: Keep[]?
- Tile 3 CheckBox: Keep[]?
... and so on

无需担心它们来自什么地图。地图信息仍然存在(它在每个图块对象上),我只是在“发布”操作中对其进行了处理,以将它们正确地分成地图。

但是现在,我想添加一个功能来说给定地图的图块列表是否完整。我的目标是一个复选框-看起来像这样:

Map Identifier map1  CheckBox: Complete? []
 - Tile 1 for map1    CheckBox: Keep[]?
 - Tile 2 for map1    CheckBox: Keep[]?
 - ... and so on
Map Identifier map2  CheckBox: Complete? []
 -Tile 1 for map2     CheckBox: Keep[]?
 - ... ect

我不知道每次尝试将有多少块图块或地图。

所以我试图做的是创建一个新的ViewModel:

    public class MultipleMapIdentifiers
    {
        [Display(Name = "Map: ")]
        public string MapIdentifier { get; set; }
        public List<TileInformation> TileInformationList{ get; set; }

        [Display(Name = "Full Run? ")]
        public bool FullRun { get; set; }
    }

然后,在返回Review视图之前,我简单地遍历了所有提交的图块,获取了不同的MapIdentifiers,然后遍历图块以查找具有相同mapID的图块,并将它们放在此视图对象的列表中

然后,我使用新的编辑器模板创建了新的视图。

首先,我只是在MultipleMapIdentifiers EditorTemplate中使用了@foreach循环来显示每个图块。展示他们很棒。调用Post时返回空列表。

因此,我第二次尝试为每个项目调用局部视图-仍然是MultipleMapsIdentifiers EditorTemplate中的Foreach循环,但是它为我跳过的TileInformation调用了一个模板,该模板可以正确用于编辑器复选框。请记住-如果我们要保留此图块或将其作为坏/重复的图块丢弃,则每个TileInformation都有其自己的复选框。

这也只会将空的Tile列表返回到Post Action。

有什么方法可以实现吗?如何获取带有其复选框的列表,并将其原封不动地返回到“发布操作”中,以便在添加到数据库之前删除不希望保留的列表?

1 个答案:

答案 0 :(得分:0)

万一有人在搜索并降落在这里:

我结束了向普通模型中添加几个[NotMapped]属性,包括第一个布尔值。如果第一个标记为true,则它将显示地图标识符字符串和其他内容,否则,它将仅使用剃刀中的隐藏字段将数据推入其余模型版本。

@if (Model.First)
{
    <div class="row mb-3 bg-info rounded">


        <div class="col-sm-2 font-weight-bold border-bottom border-light mb-2 align-items-center">
            @Html.DisplayNameFor(a => a.MapIdentifier)
        </div>
        <div class="col-sm-7 font-italic text-truncate border-bottom border-light mb-2 align-items-center">
            <div class="display-field">
                @Html.DisplayFor(a => a.MapIdentifier)
            </div>
            <div class="editor-field">
                @Html.HiddenFor(a => a.MapIdentifier)
                @Html.ValidationMessageFor(a => a.MapIdentifier)
            </div>
        </div>
        <div class="col-sm-3 border-bottom border-light mb-2">
            <p class="text-center"><span>@Html.CheckBoxFor(a => a.FullRun)</span>  <b>Was this a Complete Run?</b></p>
            <p class="text-center"><span>@Html.CheckBoxFor(a => a.MapPointsRecorded)</span>  <b>Recording Map Points?</b></p>
        </div>
        <div class="editor-field">
            @Html.HiddenFor(a => a.First)
            @Html.ValidationMessageFor(a => a.First)
        </div>
    </div>
}
else
{
    <div class="editor-field">
        @Html.HiddenFor(a => a.MapIdentifier)
        @Html.ValidationMessageFor(a => a.MapIdentifier)
    </div>
}

可能不是最优雅的解决方案,但目前仍然有效。