View Model Binding如何工作? +使用视图模型处理动态控件的最佳方法?

时间:2011-12-17 20:15:15

标签: jquery asp.net-mvc asp.net-mvc-3 viewmodel

我正在使用asp.net mvc 3并且想到处理这种情况的最佳方法是。

假设我有一个创建奖励结构的表单。在这种情况下,他们可以获得多种奖励水平

例如

$100 to $500 - get .05% back
$501 to $1000 - get 0.6% back
$1001 to $1001 - get 0.7% back
and so forth.

现在这些层以我正在创建的形式输入。可能有一个奖励等级或可能有5层或50层。我只是不知道。

选项1

对5层进行人为限制。如果他们只需要一层井,他们仍然必须通过向导形式(通过jquery)我正在创建并跳过接下来的4层屏幕(他们将需要填写相当多的字段,所以我决定做它一个巫师,所以它不会立刻压倒一切。)

    public class MasterVm
    {
        public IList<TiersVm> Tiers { get; set; }

        public MasterVm()
        {
            Tiers = new List<TiersVm>();
        }
    }

@for (int i = 0; i < Model.Tiers.Count; i++)
{
    @Html.LabelFor(x => x.Tiers[i].StartOfRange, "Start Of Range")
    @Html.TextBoxFor(x => x.Tiers[i].StartOfRange)

    @Html.LabelFor(x => x.Tiers[i].EndOfRange, "End Of Range")
    @Html.TextBoxFor(x => x.Tiers[i].EndOfRange)

    // more fields here

}

在我的控制器中,我会制作5个占位符,因此for循环将会循环5次。

选项2

使表单生成另一个层级按钮。他们点击它,将制作另一层。这样,如果他们只有一个,他们只看到一次,如果他们有100则无关紧要。

我正在考虑使用jquery clone来实现这一点,但我不知道视图模型绑定是如何工作的。看看id了吗?还是名字?

当我做选项时,我的所有控件都看起来像这样

<input id="Tiers_0__StartOfRange" type="text" value="0" name="Tiers[0].StartOfRange">

他们都有独特的id(好的)和独特的名字。我不确定在克隆代码中我是否应该删除id和名称。或者我是否需要在其中生成代码以生成如上所示的id和名称?

我将使用jquery.serializeArray()通过ajax提交所有内容,并且在控制器中我将有一个参数,View Model也应该绑定。

2 个答案:

答案 0 :(得分:1)

我不喜欢MVC3使用的开箱即用的索引模式。在我们的应用程序中,我们使用Steve Sanderson's BeginCollectionItem HTML helper。它会覆盖默认行为,并使用GUID而不是整数来索引多个项目。

我建议你做选项#2,但是在服务器上做克隆/收集项目工厂的东西,然后使用ajax将HTML返回到视图。 Steve的助手使用默认的模型绑定器,因此当您发布表单时,最终会得到一个从表单输入绑定的层模型集合。

单层的局部视图示例:

@model TiersVm
<div class="tier-item">
@using(Html.BeginCollectionItem("Tiers"))
{
    Html.LabelFor(x => x.StartOfRange, "Start Of Range")
    Html.TextBoxFor(x => x.StartOfRange)

    Html.LabelFor(x => x.EndOfRange, "End Of Range")
    Html.TextBoxFor(x => x.EndOfRange)

    // more fields here
}
</div>

当用户点击“添加图层”按钮时,您将拥有一个返回上述部分的操作方法。

public PartialViewResult GenerateTier()
{
    return PartialView(new TiersVm());
}

BeginCollectionItem帮助器将呈现所有输入名称和id,以便它们可以反弹到您正在POST的模型中:

@model MasterVm
... using BeginForm ....

<div class="tier-container"> @* clicking new tier button appends items here *@
@foreach (var tier in Model.Tiers)
{
   Html.Action("GenerateTier", "ControllerName")
}
</div>

然后使用默认模型绑定器

进行魔术
[HttpPost]
public ActionResult ReceiveInput(MasterVm masterVm)
{
    // masterVm.Tiers has been populated by the default model binder
}

答案 1 :(得分:0)

指南是元素的ID必须与ViewModel属性名称相对应 其余的都是你的决定。

如果您创建对服务器的AJAX调用,则必须使URL参数与模型属性

相对应

您可以编写一个自定义模型绑定器,根据您所需的逻辑进行绑定。自定义IModelBinder的一个示例,您可以找到here

请注意MVC团队的建议:

  

一般情况下,我们建议人们不要编写自定义模型绑定器   因为他们很难做对,很少需要他们