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

时间:2021-11-06 17:55:23

Case: I have a list of items of Class X displayed using Editor Template for Class X.

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

Problem: How can I get index of an item being processed on the inside of the Editor Template?

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

6 个解决方案

#1


8  

I've been using this HtmlExtension that returns only the needed id of an iteration. It's basically a regex on ViewData.TemplateInfo.HtmlFieldPrefix that's capturing the last number.

我一直在使用这个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;
    }
}

Can be used in an EditorFor-template like this:

可以在EditorFor-template中使用,如下所示:

@Html.Index()

#2


5  

Use a for loop instead of for each and pass the indexer into the EditorFor extension; razor should handle the rest.

使用for循环而不是每个循环并将索引器传递给EditorFor扩展;剃刀应该处理剩下的事情。

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

Update:

更新:

pass in the the index of the item using view data as show above.

使用上面显示的视图数据传递项目的索引。

In your editor template access the item via the ViewBag

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

<span> Item Index: @ViewBag.index </span>

#3


4  

Using the EditorTemplate is the best solution when viewing models that contain a list of something.

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

In order to find the index for the sub-model being rendered you can use the property that Razor sets by default:

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

ViewData.TemplateInfo.HtmlFieldPrefix

Say, for example, you have the following view models:

比如说,您有以下视图模型:

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

and

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

    public string Text {get; set;}
}

and you want to be able to edit all the "LineVM" within a "ParagraphVM". Then you would use an Editor Template so you would create a view at the following folder (if it doesn't exist) with the same name as the sub-model Views/Shared/EditorTemplates/LineVM.cshtml:

并且您希望能够编辑“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>

Assuming you have a Controller's ActionResult that is returning a View and passing a ParagrapghVM viewmodel to a view, for example Views/Paragraph/_Paragraph.cshtml:

假设您有一个Controller的ActionResult,它返回一个View并将ParagrapghVM视图模型传递给视图,例如Views / Paragraph / _Paragraph.cshtml:

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

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

This view would render as many editors for the list Lines as items contains that list. So if, for example, the property list ParagraphVM.Lines contains 3 items it would render something like:

此视图将为列表行呈现尽可能多的编辑器,因为项目包含该列表。因此,例如,如果属性列表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>

With that you can know exactly what position each items is within the list and for example use some javascript to create a carousel or whatever you want to do with it. But remember that to edit that list you don't really need to know the position as Razor takes care of it for you. If you post back the model ParagraphVM, the list Lines will have the values bound (if any) without any additional work.

通过它,您可以准确地知道每个项目在列表中的位置,例如使用一些javascript来创建轮播或任何您想要用它做的事情。但请记住,要编辑该列表,您并不需要知道Razor为您处理的位置。如果您回发模型ParagraphVM,列表行将具有绑定的值(如果有),而无需任何其他工作。

#4


4  

How about:

怎么样:

@using System
@using System.Text.RegularExpressions

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

#5


2  

You can use @Html.NameFor(m => m.AnyField). That expression will output the full name property including the index. You could extract the index there...

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

#6


0  

I think the easiest way is:

我认为最简单的方法是:

@Regex.Match(ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])")

Or as helper:

或作为帮手:

    public static string Index(this HtmlHelper html)
    {
        Match m = Regex.Match(html.ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])");
        return m.Success ? m.Value : null;
    }

Inspired by @Jona and @Ryan Penfold

灵感来自@Jona和@Ryan Penfold

#1


8  

I've been using this HtmlExtension that returns only the needed id of an iteration. It's basically a regex on ViewData.TemplateInfo.HtmlFieldPrefix that's capturing the last number.

我一直在使用这个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;
    }
}

Can be used in an EditorFor-template like this:

可以在EditorFor-template中使用,如下所示:

@Html.Index()

#2


5  

Use a for loop instead of for each and pass the indexer into the EditorFor extension; razor should handle the rest.

使用for循环而不是每个循环并将索引器传递给EditorFor扩展;剃刀应该处理剩下的事情。

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

Update:

更新:

pass in the the index of the item using view data as show above.

使用上面显示的视图数据传递项目的索引。

In your editor template access the item via the ViewBag

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

<span> Item Index: @ViewBag.index </span>

#3


4  

Using the EditorTemplate is the best solution when viewing models that contain a list of something.

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

In order to find the index for the sub-model being rendered you can use the property that Razor sets by default:

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

ViewData.TemplateInfo.HtmlFieldPrefix

Say, for example, you have the following view models:

比如说,您有以下视图模型:

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

and

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

    public string Text {get; set;}
}

and you want to be able to edit all the "LineVM" within a "ParagraphVM". Then you would use an Editor Template so you would create a view at the following folder (if it doesn't exist) with the same name as the sub-model Views/Shared/EditorTemplates/LineVM.cshtml:

并且您希望能够编辑“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>

Assuming you have a Controller's ActionResult that is returning a View and passing a ParagrapghVM viewmodel to a view, for example Views/Paragraph/_Paragraph.cshtml:

假设您有一个Controller的ActionResult,它返回一个View并将ParagrapghVM视图模型传递给视图,例如Views / Paragraph / _Paragraph.cshtml:

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

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

This view would render as many editors for the list Lines as items contains that list. So if, for example, the property list ParagraphVM.Lines contains 3 items it would render something like:

此视图将为列表行呈现尽可能多的编辑器,因为项目包含该列表。因此,例如,如果属性列表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>

With that you can know exactly what position each items is within the list and for example use some javascript to create a carousel or whatever you want to do with it. But remember that to edit that list you don't really need to know the position as Razor takes care of it for you. If you post back the model ParagraphVM, the list Lines will have the values bound (if any) without any additional work.

通过它,您可以准确地知道每个项目在列表中的位置,例如使用一些javascript来创建轮播或任何您想要用它做的事情。但请记住,要编辑该列表,您并不需要知道Razor为您处理的位置。如果您回发模型ParagraphVM,列表行将具有绑定的值(如果有),而无需任何其他工作。

#4


4  

How about:

怎么样:

@using System
@using System.Text.RegularExpressions

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

#5


2  

You can use @Html.NameFor(m => m.AnyField). That expression will output the full name property including the index. You could extract the index there...

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

#6


0  

I think the easiest way is:

我认为最简单的方法是:

@Regex.Match(ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])")

Or as helper:

或作为帮手:

    public static string Index(this HtmlHelper html)
    {
        Match m = Regex.Match(html.ViewData.TemplateInfo.HtmlFieldPrefix, @"(?!\[)\d+(?=\])");
        return m.Success ? m.Value : null;
    }

Inspired by @Jona and @Ryan Penfold

灵感来自@Jona和@Ryan Penfold