前陣子,應邀到某企業講述ASP.NET 3.5的新功能,我於課堂中展示了一個應用ListView控件的例子
玩轉ListView
文/黃忠成
前陣子,應邀到某企業講述ASP.NET 3.5的新功能,我於課堂中展示了一個應用ListView控件的例子,當學員看到此範例時,脫口而出一句【好漂亮】,讓我覺得此例應該放到Blog上跟大家分享。
這個例子事實上已寫好許久,在ASP.NET 3.5剛推出時,我對ListView控件充滿好奇,就ASP.NET 2.0所提供的資料控件,複雜易用的有GridView、FormView,簡單具延展性的有Repeater、DataList,那ListView又該放在那個位置呢?就ListView控件的功能來論,其具備了GridView、FormView複雜易用的特色,同時也具備了Repeater、DataList的延展性,下表是這些控件的比較表。
表1
功能 | GridView | FormView | Repeater | DataList | ListView |
內建編輯功能 | * | * | X | X | * |
內建刪除功能 | * | * | X | X | * |
內建新增功能 | * | * | X | X | * |
可自訂Container、Header、Item等Template | X | X | * | * | * |
支援分頁 | * | * | X | X | * |
仔細看這張表後,你應該可以了解,ListView控件是一個夾縫中的產物,也可稱為是一個具備延展性的GridView控件。
那麼問題來了,有那種例子可以充份發揮ListView控件呢?這個例子必須是GridView、DataList等控件難以達成、甚至無法達成的,我腦中一閃而過的是一個很特別的商品展示頁面,以往,在展示商品時,我們都會應用GridView來進行條列式展示,這也是GridView唯一能做的呈現,但現在有ListView,我們可以自定Container、Header、Item等Layout,再用條列式就未免太浪費了。
因此我嘗試一種新的、但能吸引目光的呈現,那就是環狀展示,也可稱為圓形展示,圖1是此想法的實現圖。
圖1
很明顯的,要完成這個例子,我們必須充份的使用網頁中常見的絕對座標來定位每個Item的位置!以ListView控件所開放的Template而言,我們可以將LayoutTemplate設成Panel,然後將每個ItemTemplate也設成Panel,然後將每個ItemTemlate中的Panel控件設成絕對座標制。結果就是下列的程式碼:
程式1
.aspx |
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <style type="text/css"> .shadowPanel { border: thin solid #000000; } .shadowPanel1 { border-style: none solid solid none; border-width: 5px; border-color: #C0C0C0; } </style> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT [BOOK_ID], [NAME], [PIC_URL] FROM [BOOKS]"></asp:SqlDataSource> <asp:ListView ID="ListView1" runat="server" DataKeyNames="BOOK_ID" DataSourceID="SqlDataSource1" style="top: 48px; left: 10px; right: 772px;" onitemdatabound="ListView1_ItemDataBound"> <LayoutTemplate> <asp:Panel ID="itemPlaceholderContainer" runat="server" style="position:absolute"> <div ID="itemPlaceholder" style="" runat="server"> </div> </asp:Panel> </LayoutTemplate> <ItemTemplate> <asp:Panel ID="container1" CssClass="shadowPanel1" style="height:154px;width:119px" runat=server> <asp:Panel ID="itemContainer1" runat="server" Height="150px" Width="113px" CssClass="shadowPanel"> <table> <tr> <td> <asp:Image ID="Img1" ImageUrl='<%# HttpUtility.HtmlEncode((string)Eval("PIC_URL")) %>' Height="148px" Width="108px" ImageAlign="Left" runat="server" /> </td> </tr> <tr> <td> <asp:Label ID="LastNameLabel" runat="server" Text='<%# HttpUtility.HtmlEncode((string)Eval("NAME")) %>' /> </td> </tr> </table> </asp:Panel> </asp:Panel> </ItemTemplate> </asp:ListView> <asp:DataPager ID="DataPager1" runat="server" PagedControlID="ListView1" PageSize="8"> <Fields> <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" /> </Fields> </asp:DataPager> </div> </form> </body> </html> |
.aspx.cs |
using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; using System.Collections.Generic; public partial class Default2 : System.Web.UI.Page { private int index = 0; protected void Page_Load(object sender, EventArgs e) { } private static List<Dictionary<string, string>> _positions = new List<Dictionary<string, string>>(); static Default2() { _positions.Add(new Dictionary<string, string>() { {"Top","19px"}, {"Left","467px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","89px"}, {"Left","321px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","201px"}, {"Left","180px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","364px"}, {"Left","318px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","446px"}, {"Left","480px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","361px"}, {"Left","636px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","203px"}, {"Left","772px"} }); _positions.Add(new Dictionary<string, string>() { {"Top","93px"}, {"Left","634px"} }); } protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e) { if (e.Item.ItemType == ListViewItemType.DataItem) { Panel pnl = (Panel)e.Item.FindControl("container1"); pnl.Style[HtmlTextWriterStyle.Height] = "154px"; pnl.Style[HtmlTextWriterStyle.Width] = "117px"; pnl.Style[HtmlTextWriterStyle.Position] = "absolute"; pnl.Style[HtmlTextWriterStyle.Top] = _positions[index]["Top"]; pnl.Style[HtmlTextWriterStyle.Left] = _positions[index]["Left"]; index++; } } } |
這個例子中,精華部份是絕對位置的設定及Dictionary的Collection Initializes。當然,這個例子要用Repeater及DataList來呈現也不是不可能,但是若真的去做時,你會發現分頁、編輯等功能都要靠程式碼來實現,ListView在這點上方便許多是吧。
本文範例下載位置
http://code6421.myweb.hinet.net/ASPNET35/ListViewDemo.zip
註:本文及範例使用的書及圖形為所屬出版社所有,如有不妥之處,請聯絡我,我會盡速移除。