Html.EditorFor(...)如何知道循环的索引和项?

时间:2013-02-02 02:56:03

标签: .net razor asp.net-mvc-4

假设您有这样的模型:

class Foo
{
    public int A {get; set;}
    public int B {get; set;}
}

class SomeModel
{
    public List<Foo> Foos { get; set; }

}

在ASP.NET mvc框架的剃刀视图中,您可以执行以下操作:

@model SomeModel

@for(int i = 0; i < Model.Foos.Count; ++i)
{
   Html.EditorFor(x => x.Foos[i]);
}

剃刀引擎会愉快地吐出包含索引的正确html,并使用正确的索引实例调用编辑器模板。

EditorFor方法是带有签名

的静态扩展方法
public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)

从签名中可以看出,它只是表达式,而唯一的上下文来自HtmlHelper实例。

我已经完成了非常有限的Expression树处理,但是从我所看到的情况来看,我看不出这种静态方法可以知道它以某种方式神奇地获取的信息。

EditorFor方法如何找出生成html名称的索引并获取传递给编辑器模板的正确实例?

1 个答案:

答案 0 :(得分:6)

您传递的是表达式,而不是x.Foos[i]的值。然后MVC评估该表达式,并确定您为其提供了一个带索引的集合。 如果你删除了整个循环,你会得到相同的结果:

Html.EditorFor(x => x.Foos)
然后,MVC将自动为集合的所有元素呈现编辑器模板并生成适当的名称。

您可以在此处详细了解MVC如何处理显示/编辑器模板:Link

编辑:为了看到这一点,我在这里写了一段随机的代码:

List<string> list = new List<string>() { "A", "B", "C" };
var tester = new ExpressionTester<List<string>>(list);
var item = tester.Foo(p => p[0]);

您还需要这门课程:

public class ExpressionTester<TModel>
{
    private TModel _list;
    public ExpressionTester(TModel list)
    {
        _list = list;
    }

    public TValue Foo<TValue>(Expression<Func<TModel, TValue>> expression)
    {
        var func = expression.Compile();
        return func.Invoke(_list);
    }
}

在Foo()中粘贴断点并查看调试中的参数expression。您将在Body下找到 - &gt;参数与表达式一起传递的索引。在Body下 - &gt;方法您将看到它实际上是一个通用列表。