很多模板引擎都有一种特殊的语法,它是foreach和else的结合.基本上,当foreach循环没有任何迭代时执行else子句.如果要在列表回退中显示某种没有项目,这可能很有用.
{% for user in users %} <li>{{ user.username|e }}</li> {% else %} <li><em>no user found</em></li> {% endfor %}
使用Razor View Engine,模板会像这样,包括对集合中项目数量的额外检查:
@foreach (var user in users) { <li>@user.UserName</li> } @if (!users.Any()) { <li><em>no user found</em></li> }
所以我的问题是:我们可以使用Razor View Engine以某种方式实现类似的优雅.
解决方法
巩固Jamiec和Martin Booth的答案.我创建了以下扩展方法.它将IEnumerable作为第一个参数,然后使用两个委托来呈现文本.在Razor Views中,我们可以向Templated Delegates传递两个这样的参数.简而言之,这意味着您可以提供模板.所以这是扩展方法以及如何调用它:
public static HelperResult Each<TItem>(this IEnumerable<TItem> items,Func<TItem,HelperResult> eachTemplate,Func<dynamic,HelperResult> other) { return new HelperResult(writer => { foreach (var item in items) { var result = eachTemplate(item); result.WriteTo(writer); } if (!items.Any()) { var otherResult = other(new ExpandoObject()); // var otherResult = other(default(TItem)); otherResult.WriteTo(writer); } }); }
并在剃刀视图中:
@Model.Users.Each( @<li>@item.Name</li>,@<li> <b>No Items</b> </li> )
总而言之,非常干净.
更新实施评论中提出的建议.此扩展方法使用一个参数循环集合中的项并返回自定义HelperResult.在那个helperresult上,如果没有找到任何项目,可以调用Else方法传入模板委托.
public static class HtmlHelpers { public static ElseHelperResult<TItem> Each<TItem>(this IEnumerable<TItem> items,HelperResult> eachTemplate) { return ElseHelperResult<TItem>.Create(items,eachTemplate); } } public class ElseHelperResult<T> : HelperResult { private class Data { public IEnumerable<T> Items { get; set; } public Func<T,HelperResult> EachTemplate { get; set; } public Func<dynamic,HelperResult> ElseTemplate { get; set; } public Data(IEnumerable<T> items,Func<T,HelperResult> eachTemplate) { Items = items; EachTemplate = eachTemplate; } public void Render(TextWriter writer) { foreach (var item in Items) { var result = EachTemplate(item); result.WriteTo(writer); } if (!Items.Any() && ElseTemplate != null) { var otherResult = ElseTemplate(new ExpandoObject()); // var otherResult = other(default(TItem)); otherResult.WriteTo(writer); } } } public ElseHelperResult<T> Else(Func<dynamic,HelperResult> elseTemplate) { RenderingData.ElseTemplate = elseTemplate; return this; } public static ElseHelperResult<T> Create(IEnumerable<T> items,HelperResult> eachTemplate) { var data = new Data(items,eachTemplate); return new ElseHelperResult<T>(data); } private ElseHelperResult(Data data) : base(data.Render) { RenderingData = data; } private Data RenderingData { get; set; } }
然后可以按如下方式调用它:
@(Model.Users .Each(@<li>@item.Name</li>) .Else( @<li> <b>No Users</b> </li> ) )