从MVC视图模型中保存重新排序的列表项

Cia*_*her 2 .net c# asp.net asp.net-mvc asp.net-mvc-4

我有一个视图模型绑定到'TreasureHuntDetails'对象,其中包含一个线索列表.这是它的数据模型的一部分.

    public TreasureHuntDetails()
    {
        Clues = new List<Clue>();
    }

    [Key]
    public int TreasureHuntId { get; set; }

    public List<Clue> Clues { get; set; }
Run Code Online (Sandbox Code Playgroud)

在页面上,我有一张桌子.foreach循环遍历线索列表以将它们添加到表中,例如

@for (int i = 0; i < Model.Clues.Count; i++)
Run Code Online (Sandbox Code Playgroud)

for循环中的表元素非常大,但这里是一个表元素列的示例:

<td>@Html.DisplayFor(m => Model.Clues[i].Location)</td>
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利.然后我使用JQuery UI来允许使用拖放重新排序表的项目,如下所示:

        <script type="text/javascript">
        $(document).ready(function()
        {
            $("#clueTable tbody").sortable().disableSelection();
        });
        </script>
Run Code Online (Sandbox Code Playgroud)

一切都很好,我可以拖放元素.

问题是我不知道如何保存元素的新顺序并将它们保存回数据库.

我尝试的第一件事就是将线索列表传递给控制器​​方法,但我发现一旦线索列表到达控制器方法,它总是为空.

例如:

@Url.Action("ViewCluePage", @Model.Clues)
Run Code Online (Sandbox Code Playgroud)

即使我发送整个@Model,其中的线索列表也始终为null.从数据模型的构造函数中删除新的列表实例化并没有解决此问题.

我尝试的另一件事是将整个表格包装成HTML表单,但线索列表仍然为空.

所以基本上,这个问题实际上是两个问题:

1)为什么在将模型对象发送到控制器后,线索列表始终为空.

2)如何保存项目列表的新订单?

更新:根据@recursive的建议,我在尝试将线索元素提交到HTML表单时看到我在哪里犯了错误.

我在for循环之外使用了这个迭代线索元素:

@Html.HiddenFor(m => m.Clues)
Run Code Online (Sandbox Code Playgroud)

我必须在for循环中添加HiddenFor行(对于每个线索项),并且对于线索项的EACH属性,例如

@Html.HiddenFor(m => m.Clues[i].Id)
Run Code Online (Sandbox Code Playgroud)

这样才能将列表项目发送到控制器,这是向前迈出的一步,但我认为我仍然需要能够在发送到控制器时反映线索项目的新顺序的代码.目前,在使用JQuery sortable()方法重新排列屏幕上元素的顺序时,这不会更改元素的顺序,因为它们存储在绑定到视图的数据模型中(@ Model.Clues).

gwi*_*003 5

1)正如@resursive在他的评论中所说,你需要在页面上有隐藏的元素,这些元素映射到你Clue班级的属性.

2)至于保持线索的顺序,你需要在数据库中添加一个列,用于保存列表中每个线索的位置,并将position属性添加到类中.所以你的班级需要包括

public int Position {get;set;}
Run Code Online (Sandbox Code Playgroud)

在创建页面时应该从数据库中提取.然后在渲染页面之前,您应该根据Position变量重新排序线索列表.

编辑:使用jquery的可排序属性.查看此主题以供参考.在停止拖动事件中(或在提交之前),循环遍历每个可拖动对象并设置对象的每个隐藏位置属性的值.

var positionIndex = 0;
$('.draggableObjectClass).each(function () {
    $(this).find('input[id$=_Position]').val(positionIndex++);
});
Run Code Online (Sandbox Code Playgroud)