【问题标题】:How to implement foreach delegate in razor viewengine?如何在剃刀视图引擎中实现 foreach 委托?
【发布时间】:2011-02-22 11:02:07
【问题描述】:

以下代码适用于 webform 视图引擎。

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

上面的代码我在razor视图中写成如下:

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

但这不起作用。

任何人都可以建议,有没有办法在剃刀视图中实现这一点?

提前致谢。

【问题讨论】:

  • 他们正在努力增加对此的支持,但目前它不起作用。

标签: asp.net asp.net-mvc razor


【解决方案1】:

你有什么理由需要这样做吗?

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

Above 做同样的事情,而且更惯用。

我看不到使用 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&lt;T&gt; 上定义扩展方法 yields 中的项目包装在此构造中的原始枚举。

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

【讨论】:

  • 其实我想知道如何让代理在剃刀中工作。例如,我有一个可枚举的扩展方法,例如 .ForEach((x,index) => { ... })。这会将索引传递给视图,因此我可以在表中添加替代行。我知道没有这个扩展方法也可以完成,但是使用扩展方法我可以删除很多代码。
  • @learner:编辑了我的答案。我认为这在 Razor 中是不可能的。
  • -1 答案不回答 OP 的问题,OP 提供的工作解决方案
【解决方案2】:

感谢您的帮助。我根据 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>)

【讨论】:

  • FWIW 您可能会通过将此方法命名为 ForEach 来解决问题,因为方法签名具有 Func&lt;RowEntity&lt;TEntity&gt;, HelperResult&gt; template 作为依赖项,我怀疑您是否会无意中调用此方法而不是您的标准 ForEach(x=>方法。
  • 为什么人们如此痴迷于编写带有委托的foreach 循环,而编写和阅读愚蠢的旧foreach 语法要简单得多?我真的希望没有人真正这样做。
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 2015-10-19
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2011-07-04
  • 2012-05-22
相关资源
最近更新 更多