Internet Explorer 8引入了三大新功能,分別是網頁快訊、加速器及搜尋提供者,本文的主題就是放在其中的Web Slice。只是網路上關於這三大功能的資料已經相當的多且完整,例如筆者之前為MSDN所撰寫的Internet Explorer 8文章(註1)中,已經對這三大功能的基本介紹及在各種平台如何實現的議題上做了許多著墨,因此本文就不再贅述什麼是Web Slice及其基本的撰寫方法了,直接將焦點放在較為實際應用面。
Using GridView To Display Web Slices
文/黃忠成
Web Slice
Internet Explorer 8引入了三大新功能,分別是網頁快訊、加速器及搜尋提供者,本文的主題就是放在其中的Web Slice。只是網路上關於這三大功能的資料已經相當的多且完整,
例如筆者之前為MSDN所撰寫的Internet Explorer 8文章(註1)中,已經對這三大功能的基本介紹及在各種平台如何實現的議題上做了許多著墨,因此本文就不再贅述什麼是Web Slice
及其基本的撰寫方法了,直接將焦點放在較為實際應用面。
了解Web Slice的運作模式
Web Slice的運作原理其實很簡單,在了解其原理之前,我們先來看一個簡單的Web Slice例子。
程式1
<div id="slice1" class="hslice"> <h2 class="entry-title">Times</h2> <div class="entry-content"> <%= DateTime.Now.ToString("g") %> </p> <img src="http://sin.stb01.s-msn.com/i/48/23559E271728628A31199AA4442B3.gif" /> </div> <p style="visibility:hidden">Updates occur every <span class="ttl">60</span> minutes.</p> </div> |
當IE 8遭遇class名稱設定為hslice的HTML Element,就會將其視為是一個Web Slice,當使用者訂閱時,IE 8會將該HTML 元素及其子元素存成一個片段的HTML區塊存在本機端,
並將來源網址一併存下來。日後需要更新時,就連回原本的網址尋找同樣id的HTML 元素,更新原先儲存的HTML 區塊。
由此可以理出兩個重點,一是Web Slice區塊必須是一個可單獨顯示的HTML 元素區塊,也就是說例如td、tr都不能當成Web Slice區塊,因為它們必須與table並存才能成為一個
可單獨顯示的區塊。
二是Web Slice區塊必須要擁有一個id,而且是一個在該網頁中唯一的id,因為IE 8在更新Web Slice區塊時,會連回來源網頁後,依據此id來擷取更新區塊內容。
在簡單的應用,例如MSN的News區塊或是最新消息,要滿足這兩點其實一點都不困難,但是如果要撰寫類似EBay這種整群列示的Web Slice,那麼這兩點就很重要了。
圖1 (Ebay的Web Slices)
用GridView來做出類似EBay的效果
當看到EBay這種應用時,許多人第一個想到的實作方式是用GridView,但實際動手時,你會遭遇到幾個困難,第一個困難是GridView每筆資料都是以TR方式顯示的,
這無法滿足Web Slice區塊必須要是一個可單獨顯示之HTML區塊的條件。
解決這個問題的方式很簡單,我們可以運用GridView的Template功能,在某一欄裡放上DIV,並加上hslice的class設定。
接著會遇到第二個困難點,那就是如何產生唯一的ID,這點就更簡單了,每個產品編號都不同,藉由單一編號即可滿足每個Web Slice擁有單一ID的要求,程式2便是這樣一個例子。
程式2
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <!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"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" DeleteCommand="DELETE FROM [BOOKS] WHERE [BOOK_ID] = @BOOK_ID" InsertCommand="INSERT INTO [BOOKS] ([BOOK_ID], [NAME], [PIC_URL], [BID_PRICE]) VALUES (@BOOK_ID, @NAME, @PIC_URL, @BID_PRICE)" SelectCommand="SELECT * FROM [BOOKS]" UpdateCommand="UPDATE [BOOKS] SET [NAME] = @NAME, [PIC_URL] = @PIC_URL, [BID_PRICE] = @BID_PRICE WHERE [BOOK_ID] = @BOOK_ID"> <DeleteParameters> <asp:Parameter Name="BOOK_ID" Type="String" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="NAME" Type="String" /> <asp:Parameter Name="PIC_URL" Type="String" /> <asp:Parameter Name="BID_PRICE" Type="Double" /> <asp:Parameter Name="BOOK_ID" Type="String" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="BOOK_ID" Type="String" /> <asp:Parameter Name="NAME" Type="String" /> <asp:Parameter Name="PIC_URL" Type="String" /> <asp:Parameter Name="BID_PRICE" Type="Double" /> </InsertParameters> </asp:SqlDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="BOOK_ID" DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None"> <RowStyle BackColor="#FFFBD6" ForeColor="#333333" /> <Columns> <asp:TemplateField> <ItemTemplate> <div id='<%# Eval("BOOK_ID") + "_SLICE" %>' class="hslice" style="width:300px"> <%# Eval("BOOK_ID") %> <span class="entry-title" style="visibility: hidden"> <%# Eval("Name") %></span> <div class="entry-content"> <p><%# Eval("Name") %></p> <asp:Image ID="Image1" runat="server" Height="120" Width="80" ImageUrl='<%# Eval("PIC_URL") %>' /> <br /> BID Price: <asp:Label ID="Label1" runat="server" Text= '<%# Eval("BID_PRICE") %>' /> </div> </div> </ItemTemplate> </asp:TemplateField> </Columns> <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" /> <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /> <AlternatingRowStyle BackColor="White" /> </asp:GridView> </div> </form> </body> </html> |
執行結果如圖2。
圖2
不過這個程式仍然不完整,因為當加上GridView分頁機制後,如果使用者訂閱的是第二頁之後的內容,那麼就會發生錯誤。
圖3
此錯誤產生原因很簡單,因為IE 8在擷取Web Slice區塊時,是回到來源網頁來搜尋同樣id的HTML 元素更新,但由於未經過PostBack機制緣故,當IE 8嘗試這麼做時,
我們的這個網頁是顯示第一頁的內容,所以IE 8便找不到同樣的id,最後導致錯誤。
解決的方法很簡單,Web Slice規格中允許我們於內描述IE 8該連回那擷取並更新Web Slice區塊,程式3是運用此技巧解決目前問題的例子。
程式3
WebForm1.aspx |
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <!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"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" DeleteCommand="DELETE FROM [BOOKS] WHERE [BOOK_ID] = @BOOK_ID" InsertCommand="INSERT INTO [BOOKS] ([BOOK_ID], [NAME], [PIC_URL], [BID_PRICE]) VALUES (@BOOK_ID, @NAME, @PIC_URL, @BID_PRICE)" SelectCommand="SELECT * FROM [BOOKS]" UpdateCommand="UPDATE [BOOKS] SET [NAME] = @NAME, [PIC_URL] = @PIC_URL, [BID_PRICE] = @BID_PRICE WHERE [BOOK_ID] = @BOOK_ID"> <DeleteParameters> <asp:Parameter Name="BOOK_ID" Type="String" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="NAME" Type="String" /> <asp:Parameter Name="PIC_URL" Type="String" /> <asp:Parameter Name="BID_PRICE" Type="Double" /> <asp:Parameter Name="BOOK_ID" Type="String" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="BOOK_ID" Type="String" /> <asp:Parameter Name="NAME" Type="String" /> <asp:Parameter Name="PIC_URL" Type="String" /> <asp:Parameter Name="BID_PRICE" Type="Double" /> </InsertParameters> </asp:SqlDataSource> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="BOOK_ID" DataSourceID="SqlDataSource1" ForeColor="#333333" GridLines="None" AllowPaging="True" PageSize="5"> <RowStyle BackColor="#FFFBD6" ForeColor="#333333" /> <Columns> <asp:TemplateField> <ItemTemplate> <div id='<%# Eval("BOOK_ID") + "_SLICE" %>' class="hslice" style="width:300px"> <a href='<%#"BookDetail.aspx?ID="+Eval("BOOK_ID") %>' rel="feedurl" style="visibility:hidden"></a> <%# Eval("BOOK_ID") %> <span class="entry-title" style="visibility: hidden"> <%# Eval("Name") %></span> <div class="entry-content"> <p> <%# Eval("Name") %></p> <asp:Image ID="Image1" runat="server" Height="120" Width="80" ImageUrl='<%# Eval("PIC_URL") %>' /> <br /> BID Price: <asp:Label ID="Label1" runat="server" Text='<%# Eval("BID_PRICE") %>' /> </div> </div> </ItemTemplate> </asp:TemplateField> </Columns> <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" /> <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /> <AlternatingRowStyle BackColor="White" /> </asp:GridView> </div> </form> </body> </html> |
BookDetail.aspx |
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="BookDetail.aspx.cs" Inherits="WebApplication1.BookDetail" %> <!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"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT * FROM [BOOKS] WHERE ([BOOK_ID] = @BOOK_ID)"> <SelectParameters> <asp:QueryStringParameter Name="BOOK_ID" QueryStringField="ID" Type="String" /> </SelectParameters> </asp:SqlDataSource> <asp:FormView ID="FormView1" runat="server" DataKeyNames="BOOK_ID" DataSourceID="SqlDataSource1"> <ItemTemplate> <div id='<%# Eval("BOOK_ID") + "_SLICE" %>' class="hslice"> <span class="entry-title" style="visibility: hidden"> <%# Eval("Name") %></span> <div class="entry-content"> <p><%# Eval("Name") %></p> <asp:Image ID="Image1" runat="server" Height="120" Width="80" ImageUrl='<%# Eval("PIC_URL") %>' /> <br /> BID Price: <asp:Label ID="Label1" runat="server" Text='<%# Eval("BID_PRICE") %>' /> </div> </div> </ItemTemplate> </asp:FormView> </div> </form> </body> </html> |
由於要指定另一個顯示Web Slice的來源,因此我們製作了另一個網頁BookDetail.aspx來顯示單筆資料,並於WebForm1.aspx的Web Slice區塊中明確以
<a href='<%#"BookDetail.aspx?ID="+Eval("BOOK_ID") %>' rel="feedurl" style="visibility:hidden"></a> |
來告知IE 8,當需要擷取、更新Web Slice內容時,請至BookDetail.aspx取得同名id的HTML Element。此例最終的執行結果如圖4。
圖4
除了可指定來源外,Web Slice規格也可另外指定當使用者於Web Slice上按下【開啟這個網頁快訊的網頁】時,所前往的網址,下面是一個簡單的示例。
<a href='<%#"BookDetail.aspx3?ID="+Eval("BOOK_ID") %>' rel="bookmark" style="visibility:hidden"></a> |
有一點要提醒各位,以本例來說,這一行必須放在BookDetail.aspx(I更新Web Slice時所指定的擷取,更新網址)中,而非WebForm1.aspx,如程式4的片段。
程式4
<asp:FormView ID="FormView1" runat="server" DataKeyNames="BOOK_ID" DataSourceID="SqlDataSource1"> <ItemTemplate> <div id='<%# Eval("BOOK_ID") + "_SLICE" %>' class="hslice"> <span class="entry-title" style="visibility: hidden"> <%# Eval("Name") %></span> <div class="entry-content"> <p><%# Eval("Name") %></p> <a href='<%#"BookDetail.aspx3?ID="+Eval("BOOK_ID") %>' rel="bookmark" style="visibility:hidden"></a> <asp:Image ID="Image1" runat="server" Height="120" Width="80" ImageUrl='<%# Eval("PIC_URL") %>' /> <br /> BID Price: <asp:Label ID="Label1" runat="server" Text='<%# Eval("BID_PRICE") %>' /> </div> </div> </ItemTemplate> </asp:FormView> |