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

时间:2022-09-26 20:58:22

Suppose you have a model like so:

假设你有这样一个模型:

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

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

}

In a razor view on the ASP.NET mvc framework, you can do the following:

在一个刀片视图中ASP。NET mvc框架,你可以做以下事情:

@model SomeModel

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

And the razor engine will happily spit out the correct html containing the index, and will call the editor template with the correct indexed instance.

razor引擎会很高兴地吐出包含索引的正确html,然后用正确的索引实例调用编辑器模板。

The EditorFor method is a static extension method with the signature

编辑器方法是带有签名的静态扩展方法

public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression
)

From the signature, it is clear that it is simply taking an expression, and the only context is coming from the HtmlHelper instance.

从签名中可以明显看出,它只是取一个表达式,惟一的上下文来自HtmlHelper实例。

I have done very limited Expression tree processing, but from what I have seen, I can't see any way that this static method could know the information that it is somehow magically getting.

我已经做了非常有限的表达式树处理,但是从我所看到的,我看不出这个静态方法有什么方法可以知道它神奇地获得的信息。

How can the EditorFor method figure out the index for generating html names and get the correct instance to pass to the editor template?

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

1 个解决方案

#1


5  

You are passing it an expression, not the value of x.Foos[i]. MVC then evaluates that expression and figures out that you gave it a collection with an index. You would get the same result if you removed your entire loop and did:

传递给它的是表达式,而不是x.Foos[i]的值。然后MVC计算这个表达式,并计算出你给它一个带有索引的集合。如果你去掉整个循环,你会得到相同的结果:

Html.EditorFor(x => x.Foos)

MVC will then automatically render the editor template for all elements of the collection and generate proper names.

然后,MVC将自动呈现集合所有元素的编辑器模板并生成专有名称。

You can read more about how MVC handles display/editor templates here: Link

您可以在这里阅读更多关于MVC如何处理显示/编辑器模板的内容:链接

EDIT : To see this in action, here's a random piece of code I scribbled:

编辑:为了看到这一点,我随便写了一段代码:

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

You'll also need this class:

你也需要这门课:

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);
    }
}

Stick a breakpoint in Foo() and look at the parameter expression in debug. You'll find under Body -> Arguments the index you passed with the expression. Under Body -> Method you'll see that it is in fact a generic list.

在Foo()中插入断点,并查看debug中的参数表达式。您将在Body ->参数下找到与表达式一起传递的索引。在Body ->方法下,您将看到它实际上是一个泛型列表。

#1


5  

You are passing it an expression, not the value of x.Foos[i]. MVC then evaluates that expression and figures out that you gave it a collection with an index. You would get the same result if you removed your entire loop and did:

传递给它的是表达式,而不是x.Foos[i]的值。然后MVC计算这个表达式,并计算出你给它一个带有索引的集合。如果你去掉整个循环,你会得到相同的结果:

Html.EditorFor(x => x.Foos)

MVC will then automatically render the editor template for all elements of the collection and generate proper names.

然后,MVC将自动呈现集合所有元素的编辑器模板并生成专有名称。

You can read more about how MVC handles display/editor templates here: Link

您可以在这里阅读更多关于MVC如何处理显示/编辑器模板的内容:链接

EDIT : To see this in action, here's a random piece of code I scribbled:

编辑:为了看到这一点,我随便写了一段代码:

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

You'll also need this class:

你也需要这门课:

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);
    }
}

Stick a breakpoint in Foo() and look at the parameter expression in debug. You'll find under Body -> Arguments the index you passed with the expression. Under Body -> Method you'll see that it is in fact a generic list.

在Foo()中插入断点,并查看debug中的参数表达式。您将在Body ->参数下找到与表达式一起传递的索引。在Body ->方法下,您将看到它实际上是一个泛型列表。