Asp.net mvc 如何在编辑器模板中获取序列/数组索引?

Asp.net mvc 如何在编辑器模板中获取序列/数组索引?,asp.net-mvc,asp.net-mvc-4,razor,razor-2,Asp.net Mvc,Asp.net Mvc 4,Razor,Razor 2,案例: 我有一个使用X类编辑器模板显示的X类项目列表 问题: 如何获取编辑器模板内部正在处理的项目的索引?使用for循环而不是for each,并将索引器传递到编辑器for扩展中;剩下的就用剃刀了 @for(var i = 0; i < Model.count(); i++) { @Html.EditorFor(m => Model.ToArray()[i], new { index = i }) } for(var i=0;iModel.ToArray()[i],新的{i

案例: 我有一个使用X类编辑器模板显示的X类项目列表

问题:
如何获取编辑器模板内部正在处理的项目的索引?

使用for循环而不是for each,并将索引器传递到
编辑器for
扩展中;剩下的就用剃刀了

@for(var i = 0; i < Model.count(); i++)
{
    @Html.EditorFor(m => Model.ToArray()[i], new { index = i })
}
for(var i=0;iModel.ToArray()[i],新的{index=i}) } 更新:

使用如上所示的视图数据传入项的索引

在编辑器模板中,通过ViewBag访问项目

<span> Item Index: @ViewBag.index </span>
项目索引:@ViewBag.Index

您可以使用@Html.NameFor(m=>m.AnyField)。该表达式将输出包含索引的全名属性。您可以在那里提取索引…

在查看包含内容列表的模型时,使用EditorTemplate是最好的解决方案

为了找到正在渲染的子模型的索引,可以使用Razor默认设置的属性:

ViewData.TemplateInfo.HtmlFieldPrefix
例如,假设您有以下视图模型:

public class ParagraphVM
{
    public int ParagraphId { get; set; }
    public List<LineVM> Lines { get; set; }
}
您希望能够编辑“ParagraphVM”中的所有“LineVM”。然后,您将使用编辑器模板,以便在以下文件夹(如果不存在)中创建一个与子模型
Views/Shared/EditorTemplates/LineVM.cshtml
同名的视图:

@model MyProject.Web.MVC.ViewModels.Paragraphs.LineVM
@{
     //this will give you the List's element like Lines[index_number]
     var field = ViewData.TemplateInfo.HtmlFieldPrefix;
}
<div id="@field">
    @Html.EditorFor(l => l.Text)
</div>
@model MyProject.Web.MVC.ViewModels.Paragraphs.ParagraphVM

@using (Html.BeginForm("Details", "Paragraphs", FormMethod.Post))
{
    @Html.EditorFor(p => p.Lines)
}
此视图将为列表行呈现与包含该列表的项一样多的编辑器。 因此,例如,如果属性列表ParagraphVM.Lines包含3项,它将呈现如下内容:

<div id="#Lines[0]">
   <input id="Lines_0__Text name="Lines[0].Text"/>
</div>
<div id="#Lines[1]">
   <input id="Lines_1__Text name="Lines[1].Text"/>
</div>
<div id="#Lines[2]">
   <input id="Lines_2__Text name="Lines[2].Text"/>
</div>

那么:

@using System
@using System.Text.RegularExpressions

var i = Convert.ToInt32(Regex.Matches(
             ViewData.TemplateInfo.HtmlFieldPrefix,
             @"\[([0-9]+)?\]")[0].Groups[1].ToString());

我一直在使用这个HtmlExtension,它只返回迭代所需的id。它基本上是一个正则表达式,位于
ViewData.TemplateInfo.HtmlFieldPrefix
上,用于捕获最后一个数字

public static class HtmlExtensions
    public static MvcHtmlString Index(this HtmlHelper html)
    {
        var prefix = html.ViewData.TemplateInfo.HtmlFieldPrefix;
        var m = Regex.Match(prefix, @".+\[(\d+)\]");
        if (m.Success && m.Groups.Count == 2) 
            return MvcHtmlString.Create(m.Groups[1].Value);
        return null;
    }
}
可在EditorFor模板中使用,如下所示:

@Html.Index()

我认为最简单的方法是:

或作为助手:


灵感来源于@Jona和@Ryan Penfold

,但是我怎么知道EditorTemplate中的“I”呢?如果你在EditorTemplate中使用
@Html.EditorFor
,你就不需要知道项目的索引,Razor会恰当地命名元素,这样它们就会发回一个集合。但是,如果希望以其他方式使用索引,可以在ViewData中传递它。请参阅编辑。这将起作用!:)我唯一想知道的是,索引就在那里。剃刀知道这一点。你怎么能把它弄出来?你说的“弄出来”是什么意思?你会怎么处理它。我想说的是一个很长的故事,不适合这篇文章。我可以说,它涉及到一个大型应用程序的维护,我修改任何东西的自由度只有这么大。这是正确的,但有一个更好的选择,直接提取它。见下面我的答案。
@Html.Index()
@Regex.Match(ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])")
    public static string Index(this HtmlHelper html)
    {
        Match m = Regex.Match(html.ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])");
        return m.Success ? m.Value : null;
    }