用于IEnumerable <string>的ASP.NET MVC模型绑定可以改变模型吗?

Ste*_*ook 1 asp.net-mvc jquery

我的视图模型具有以下属性:

public IEnumerable<string> Names { get; set; }
Run Code Online (Sandbox Code Playgroud)

我的视图使用一个简单的标记显示该信息,该标记呈现为:

<div id="names">
    <ul>
        <li>Name1<img src="/delete.png"/></li>
        <li>Name2<img src="/delete.png"/></li>
        <li>Name3<img src="/delete.png"/></li>
    </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

每个名称上的图像允许您使用一些jQuery删除当前名称

$('#names li img').click(function () {
    $(this).closest('li').remove();
});
Run Code Online (Sandbox Code Playgroud)

我希望有一些方法可以将我对jQuery列表的更改反映在我的模型上.这种行为可以通过MVC编辑器模板完成吗?

我知道我可以创建一个带有分隔字符串的隐藏输入并将其解析出来,但我希望我的视图和我的控制器能够轻松处理此列表.

我想如果我在ul元素中添加了一个名字或一个id,那么模型绑定器就能够读取li元素并构造一个列表但是没有用.

Joh*_*son 6

尝试使用属性的名称(在您的情况下为"Names")添加列表项的隐藏输入,并使用方括号中的项目索引.这肯定有效:

<div id="names">
    <ul>
    <% for (int i = 0; i < Model.Names.Count; i++ ) { string name = Model.Names.ElementAt(i); %>
        <li>
            <%: Html.Hidden("Names[" + i + "]", name) %><%: name %><img src="/delete.png"/>
        </li>
    <% } %>
    </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

模型绑定器需要某种上下文来决定如何绑定复杂类型.通过提供具有正确名称的隐藏元素,它具有足够的上下文来确定该项属于索引i处的Names属性.如果您不包含索引,它将使用一组有限的项(意味着您无法在列表中添加或删除项,并调用.Add().Remove()将抛出异常).

虽然我同意jQuery方法可行,但如果你的页面的其他部分没有使用JSON那么为什么要关闭一个?隐藏元素上的名称完全相同,为其索引提供名称/值对.只有这样,模型绑定器才能为您完成工作(以低于华丽的视图语法的价格).从好的方面来说,没有必要的javascript来正确绑定这个模型.

如果您正在使用IEnumerable<string>ICollection<string>,您必须.ElementAt(i)像上面的样本一样使用.如果您使用的是IList<string>或者string[],你可以使用一个索引来代替.

编辑: 解决删除问题

为您的字符串创建另一个视图模型,因此您将IEnumerable<NameViewModel> Names { get; set; }在实际视图模型上具有属性(代替IEnumerable<string>).NameViewModel将如下所示:

public class NameViewModel
{
    public string Name { get; set; }
    public bool IsDeleted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后,添加一个隐藏的元素IsDeleted<li>.请记住,模型绑定器需要适当的上下文名称.将属性添加到索引名称后,隐藏的输入将如下所示:

<%: Html.Hidden("Names[" + i + "].Name", name.Name) %>
<%: Html.Hidden("Names[" + i + "].IsDeleted", name.IsDeleted) %>
Run Code Online (Sandbox Code Playgroud)

在您的jQuery删除代码中,找到隐藏元素并将值设置为True,并调用.hide()列表项.当您将表单发布到服务器时,您的操作方法可以找出应该删除的内容,如下所示:

var names = model.Names.Where(name => name.IsDeleted).Select(t => t.Name);
Run Code Online (Sandbox Code Playgroud)