ListView 是 ASP.NET 3.5 引入的最強資料控件:完全掌控 HTML 輸出、內建分頁/排序/編輯、支援 DataPager、模板豐富。本文深入三大進階主題:**巢狀 ListView 建構多層選單**、**繼承擴展事件模型實現「資料驅動多模板」**、**CSS 友好輸出優於 Menu 控件的表格佈局**。
資料結構:List,MenuItem 含 Children 屬性 (遞迴)。
<asp:ListView ID="lvlMenu" runat="server" DataSource="<%# GetRootMenus() %>">
<LayoutTemplate>
<ul id="menu-root" class="vertical-menu">
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<a href="<%# Eval('Url') %>"><%# Eval('Text') %></a>
<!-- 遞迴巢狀 ListView -->
<asp:ListView ID="lvlSubMenu" runat="server"
DataSource="<%# Eval('Children') %>"
Visible='<%# ((List<MenuItem>)Eval("Children")).Count > 0 %>'>
<LayoutTemplate>
<ul class="sub-menu">
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li><a href="<%# Eval('Url') %>"><%# Eval('Text') %></a></li>
</ItemTemplate>
</asp:ListView>
</li>
</ItemTemplate>
</asp:ListView>
後端遞迴繫結:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) lvlMenu.DataBind(); // 巢狀子控件會自動觸發 DataBind
}
預設 ItemDataBound 僅能修改樣式/屬性,**無法切換整個模板結構**。解決方案:繼承 ListView,覆寫 CreateItem 依資料動態決定模板。
public class SmartListView : ListView
{
// 註冊模板選擇器委派
public Func
使用範例:
// 頁面
lvProducts.TemplateSelector = item =>
{
var p = (Product)item;
if (p.IsFeatured) return "FeaturedProduct";
if (p.IsOnSale) return "SaleProduct";
return "NormalProduct";
};
| 特性 | Menu 控件 (預設) | ListView + CSS |
|---|---|---|
| HTML 結構 | <table> 佈局,語意差、難樣式化 | <ul><li> 語意化,CSS 完全掌控 |
| 飛出子選單 | 內建 JS,行為固定 | 純 CSS :hover / :focus-within,無 JS 依賴 |
| 無障礙 (a11y) | 需額外屬性 | 原生語意標籤,螢幕閱讀器友好 |
| 響應式設計 | 困難 | 媒體查詢輕鬆切換桌面/行動版面 |
ListView 不只是 DataList 的加強版,更是**「HTML 掌控權回歸開發者」**的里程碑。善用巢狀模板建構分層 UI、繼承擴展實現資料驅動多模板、配合現代 CSS 打造無障礙響應式選單,是 ASP.NET Web Forms 時代的最佳實踐典範。