16

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

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

4

6 回答 6

14

我一直在使用这个 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()
于 2016-02-24T07:48:33.587 回答
5

使用 for 循环而不是 for each 并将索引器传递给EditorFor扩展;剃须刀应该处理其余的。

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

更新:

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

在您的编辑器模板中通过 ViewBag 访问该项目

<span> Item Index: @ViewBag.index </span>
于 2013-06-19T17:51:26.887 回答
5

在查看包含某项列表的模型时,使用 EditorTemplate 是最佳解决方案。

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

ViewData.TemplateInfo.HtmlFieldPrefix

例如,假设您有以下视图模型:

public class ParagraphVM
{
    public int ParagraphId { get; set; }
    public List<LineVM> Lines { get; set; }
}

public class LineVM
{
    public int Id { get; set; }

    public string Text {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>

假设您有一个控制器的 ActionResult 正在返回一个视图并将 ParagrapghVM 视图模型传递给一个视图,例如Views/Paragraph/_Paragraph.cshtml

@model MyProject.Web.MVC.ViewModels.Paragraphs.ParagraphVM

@using (Html.BeginForm("Details", "Paragraphs", FormMethod.Post))
{
    @Html.EditorFor(p => p.Lines)
}

此视图将为列表 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>

有了它,您可以准确地知道每个项目在列表中的位置,例如使用一些 JavaScript 来创建轮播或任何您想用它做的事情。但请记住,要编辑该列表,您实际上并不需要知道位置,因为 Razor 会为您处理它。如果您回发模型 ParagraphVM,则列表 Lines 将绑定值(如果有),无需任何额外工作。

于 2015-05-26T02:49:19.873 回答
5

怎么样:

@using System
@using System.Text.RegularExpressions

var i = Convert.ToInt32(Regex.Matches(
             ViewData.TemplateInfo.HtmlFieldPrefix,
             @"\[([0-9]+)?\]")[0].Groups[1].ToString());
于 2015-08-20T13:26:10.597 回答
3

我认为最简单的方法是:

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

灵感来自@Jona 和@Ryan Penfold

于 2016-06-27T13:18:40.613 回答
2

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

于 2015-04-01T12:44:49.240 回答