Dot-Net
優雅的 foreach - else 在 Razor 中構造
許多模板引擎都有一種特殊的語法,它是
foreach和的組合else。基本上,當循環沒有任何迭代else時,就會執行該子句。如果您想在列表備份foreach中顯示某種無項目,這可能很有用。{% for user in users %} <li>{{ user.username|e }}</li> {% else %} <li><em>no user found</em></li> {% endfor %}使用 Razor 視圖引擎,模板會像這樣,涉及對集合中項目數量的額外檢查:
@foreach (var user in users) { <li>@user.UserName</li> } @if (!users.Any()) { <li><em>no user found</em></li> }所以我的問題是:我們能否使用 Razor 視圖引擎以某種方式實現類似的優雅。
鞏固 Jamiec 和 Martin Booth 的答案。我創建了以下擴展方法。它需要一個 IEnumerable 作為第一個參數,然後是兩個用於呈現文本的委託。在 Razor 視圖中,我們可以在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); } }); }在 Razor 視圖中:
@Model.Users.Each( @<li>@item.Name</li>, @<li> <b>No Items</b> </li> )總而言之,很乾淨。
更新實施評論中提出的建議。此擴展方法採用一個參數來遍歷集合中的項目並返回自定義 HelperResult。在該幫助結果上,可以呼叫該
Else方法以傳入模板委託,以防找不到任何項目。public static class HtmlHelpers { public static ElseHelperResult<TItem> Each<TItem>(this IEnumerable<TItem> items, Func<TItem, 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, Func<T, 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> ) )