如何在Razor视图引擎中实现foreach委托?

3
以下代码适用于WebForm视图引擎。
<% Model.Categories.ForEach(x => { %>
    <li><a href="#">@x.Name</a></li>
<% }) %>

我在 Razor 视图中编写了以下代码:
``` html

我写的上面的代码如下:

```
@Model.Categories.ForEach(x => {
  <li><a href="#">@x.Name</a></li>
})

但这不起作用。

有人能建议一下,在Razor视图中有什么方法可以实现这个吗?

提前致谢。


他们正在努力添加对此的支持,但目前还无法正常工作。 - Buildstarted
2个回答

7

你需要这样做的原因是什么?

@foreach(var x in Model.Categories) {
    <li><a href="#">@x.Name</a></li>
}

以上代码执行的效果完全相同,而且更符合惯用语。

我无法找到一种使用Razor语法输出.ForEach()委托结果的方法。Razor期望调用的方法或属性返回一个值,然后将其发出到视图输出中。由于.ForEach()不返回任何内容,因此无法处理它:

无法将类型 'void' 显式转换为 'object'

你可以这样简洁地拥有迭代器索引:

@foreach (var item in Model.Categories.Select((cat, i) => new { Item = cat, Index = i })) {
   <li><a href="#">@x.Index - @x.Item.Name</a></li>
}

如果你想将这个方法定义为扩展方法而不是匿名类型,你可以创建一个类来保存Item, Index对,并在IEnumerable<T>上定义一个扩展方法,该方法使用这种结构包装原始可枚举对象中的项。

public static IEnumerable<IndexedItem<T>> WithIndex<T>(this IEnumerable<T> input)
{ 
    int i = 0;
    foreach(T item in input)
        yield return new IndexedItem<T> { Index = i++, Item = item };
}

这个类:

public class IndexedItem<T>
{
    public int Index { get; set; }
    public T Item { get; set; }
}

使用方法:

@foreach(var x in Model.Categories.WithIndex()) {
    <li><a href="#">@x.Index - @x.Item.Name</a></li>
}

实际上我想知道如何在Razor中使委托工作。例如,我有一个可枚举的扩展方法,像.ForEach<T>((x,index) => { ... })。这将索引传递给视图,因此我可以在表格中添加替代行。我知道可以不使用这些扩展方法来完成,但是使用扩展方法可以减少很多代码。 - learner
@learner:我编辑了我的答案。我认为在Razor中这是不可能的。 - jevakallio
-1个答案没有回答楼主的问题,楼主提供了可行的解决方案。 - Chris Marisic

5
感谢您的帮助。我通过Phil Haack的以下文章找到了如何在Razor中实现委托。 Templated Razor Delegates 下面是IEnumerable的扩展代码:
public static HelperResult ForEachTemplate<TEntity>(
        this IEnumerable<TEntity> items, 
        Func<RowEntity<TEntity>, HelperResult> template)
{
    return new HelperResult(writer =>
               {
                   var index = 0;
                   foreach (var item in items)
                   {
                       template(new RowEntity<TEntity> { 
                               Index = index, 
                               Value = item }).WriteTo(writer);
                       index++;
                   }
               });
}

public class RowEntity<TEntity>
{
    public int Index { get; set; }
    public TEntity Value { get; set; }
}

视图模型是:

// IEnumerable<Person>

public class Person
{
    public string Name { get; set; }
}

并且使用该扩展方法:

@Model.ForEachTemplate(@<p>Index: @item.Index Name: @Item.Value.Name</p>)

就此而言,您可能只需将此方法命名为“ForEach”,因为方法签名具有Func<RowEntity<TEntity>, HelperResult> template作为依赖项,我怀疑您不会意外调用此方法,而不是您的标准ForEach(x=> method)。 - Chris Marisic
为什么人们如此痴迷于使用委托写foreach循环,当使用愚蠢而古老的foreach语法来编写并且阅读更简单呢?我真的希望没有人会这样做。 - Aaronaught

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接