翻譯:Picasa Style Photo Album Using ListView Control in ASP.Net 3.5

Picasa Style Photo Album Using ListView Control in ASP.Net 3.5

今天看到一篇比較好的文章,特此翻譯出來,原文地址:http://www.codedigest.com/Articles/ASPNET/232_Picasa_Style_Photo_Album_Using_ListView_Control_in_ASPNet_35.aspx 

源碼下載:   http://www.codedigest.com/Articles/ArticleFiles/ZIPS/232.zip

簡介:

     ListView 是ASP.Net 3.5中新發布的數據綁定控件.  我在  ListView Control in ASP.Net 3.5 一文中初步介紹了其用法.ListView是數據綁定控件中最靈活的控件,可以用任何自定義格式顯示數據。此文將用ListView創建Google’s Picasa 類型相冊. 但是 picasa 功能強大,我們只是實現顯示相冊和圖片。

預覽:

     不需要介紹Google’s Picasa 了,在相片共享方面它已得到廣泛應用。Picasa 是基於web 的 相冊,用戶可以再此創建相冊、上傳相片,與親朋好友共享。閱讀此片文章之前,最好對它的工作方式做一些瞭解,至少要知道我們用ListView要實現的功能。Picasa 顯示相冊的列表,以其中一種相片做爲封面(圖1)。點擊相冊,將會進入顯示上傳相片縮略圖的列表界面(圖2)。點擊縮略圖,可以看到原始相片。在相片全圖下,可以向前後導航(圖3).  我不善於UI設計; 對如此差的UI表示抱歉。

圖1 - 相冊image

圖2 – 相冊縮略圖image

圖3 – 相片image

接下來,我們將用ListView實現Picasa類似的相冊。如前所說,Picasa提供了很多功能,我們僅僅實現上面所說的功能,來幫助理解ListView的靈活性。

數據庫設計:

     進入實現之前,幫助理解,我們將看看存儲相冊信息的數據庫如何設計。參考下圖,數據庫包含2張表:

1. Album(相冊) – 存儲相冊信息。 DefaultPhotID字段存儲封面相片。

2. PhotAlbum(相片) –包含相冊的所有信息。Photo列存儲相片路徑。根據需要你可以改變字段大小。

image

接下來,進入實現部分。

創建相冊列表:

     相冊頁面,我們將每行平鋪顯示3個相冊,例如,水平重複顯示相片,參考圖1。要建立新相冊,在ListView的最下面有個“Create New Album” 鏈接。點擊此鏈接,將移動到ListView的最後一列,下面我們來看看如何實現。

     要在ListView中顯示數據,首先,我們必須要定義好如下模版,Layout Template 和 Item Template,可在ListView Control in ASP.Net 3.5 瞭解更多。

     另外,我們用Group Template 來平鋪分組。 用GroupItemCount屬性來限制每行顯示項的數量。

     要顯示“Create New Album” 鏈接, 要用到ListView 的另一個模版InsertItemTemplate。InsertItemTemplate中的內容將被顯示爲新增項。  設置InsertItemPosition屬性 決定InsertItemTemplate的顯示位置。此文中是LastItem。ListView 最終代碼如下:

<asp:ListView ID="lvAlbums" runat="server"
    DataSourceID="SqlDataSource1" GroupItemCount="3" 
    InsertItemPosition="LastItem">            
    <LayoutTemplate>                
            <table border="1">
               <tr ID="groupPlaceholder" runat="server">
               tr>
            table>                       
    LayoutTemplate>                                              
    <GroupTemplate>
            <tr>
                <td ID="itemPlaceholder" runat="server">
                td>
            tr>
     GroupTemplate>             
     <ItemTemplate>
            <td id="Td3" width="150px" height="150px" align="center" style="background-color: #e8e8e8;color: #333333;">
            <asp:HiddenField ID="hfPhotoID" runat="server" Value='<%# Eval("DefaultPhotID") %>' />
            <a href='<%# "Photos.aspx?AlbumID="+Eval("AlbumID") %>'> 
            <asp:Image CssClass="Timg" runat="server" ID="imPhoto" ImageUrl='<%# "ThumbNail.ashx?ImURL="+Eval("Photo") %>' />
            a>
            <br />                    
            <b><asp:Label ID="lblAlbumName" runat="server" Text='<%# Eval("AlbumName") %>'>asp:Label>   b>
            td>                
        ItemTemplate>
        
        <InsertItemTemplate>
        <td id="Td3" width="150px" height="150px" runat="server" align="center" style="background-color: #e8e8e8;color: #333333;">
        <a href="CreateAlbum.aspx">                    
            Create New Album
        a>
        td>              
        InsertItemTemplate>             
asp:ListView>
 
<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
    ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 

SelectCommand="SELECT Album.AlbumID, Album.DefaultPhotID, Album.AlbumName, PhotAlbum.Photo FROM Album INNER JOIN PhotAlbum

ON Album.DefaultPhotID = PhotAlbum.PhotoID">


asp:SqlDataSource>

在上面代碼中, 我設置GroupItemCount 爲 3。增加這個值可以增加相冊每行顯示的數量。數據綁定用的是SqlDataSource。

既然,相冊封面爲相冊中的相片(Album表DefaultPhotID列), 要將縮略圖做爲相冊封面. 要這樣做, 就要用HttpHandler[ThumbNail.ashx] 將原始相片轉換爲縮略圖.

下面就是HttpHanlder 實現從原始圖生成(100x100)縮略圖.

<%@ WebHandler Language="C#" Class="ThumbNail" %>
 
using System;
using System.Web;
using System.Drawing;
using System.IO;
 
public class ThumbNail : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        string imageurl = context.Request.QueryString["ImURL"];
        string str = context.Server.MapPath(".") + imageurl;
        Bitmap bmp = new Bitmap(str);
        System.Drawing.Image img = bmp.GetThumbnailImage(100, 100, null, IntPtr.Zero);
        MemoryStream ms = new MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        byte[] bmpBytes = ms.GetBuffer();
        img.Dispose();
        ms.Close();
 
        context.Response.BinaryWrite(bmpBytes);
        context.Response.End();    
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }
 
}

下一步, 點擊 “Create New Album” 鏈接到CreateAlbum.aspx 頁面創建新相冊. 一旦相冊建立之後, 將顯示(ImageUpload.aspx) 頁面進行相片上傳. 參考下圖:

CreateAlbum.aspx

image

ImageUpload.aspx

image

我不打算討論這些頁面的實現方法,不在此文範疇。你可以下載代碼查看。

最後,當用戶點擊相冊,將跳到 (photos.aspx)頁面,在此顯示相片縮略圖列表。

Displaying photos in Thumbnail View:

在photos.aspx 頁面, 將從QueryString中獲取AlbumId。同樣, 用GroupTemplatee每行顯示3個.參考圖2. 在圖2,相片縮略圖列表(右邊內容)又ListView顯示,而左邊的顯示相冊信息的內容是分開處理的.

要顯示每幅照片的縮略圖, 同樣用HttpHandler [ThumbNail.ashx]. 可以考慮在上傳時就存儲縮略圖,可以改進性能。本方法中,用戶每次查看相冊都會生成縮略圖,這可以通過在上傳時就存儲縮略圖才避免。可以參考此處 Upload image to file system and create thumbnail image on the fly in C# and ASP.Net

最終, ListView 類似如,

<asp:ListView ID="lvPhotos" runat="server" DataKeyNames="AlbumID" 
    DataSourceID="SqlDataSource1" GroupItemCount="3">            
    <LayoutTemplate>               
           <table ID="groupPlaceholderContainer" runat="server" border="0" cellpadding="0" cellspacing="0">
                 <tr ID="groupPlaceholder" runat="server">
                 tr>
           table>                        
    LayoutTemplate>                        
    <GroupTemplate>
            <tr ID="itemPlaceholderContainer" runat="server">
                <td ID="itemPlaceholder" runat="server">
                td>
            tr>
        GroupTemplate>           
        <ItemTemplate>
            <td runat="server" align="center" style="background-color: #e8e8e8;color: #333333;">                    
            <a href='<%# "PhotoViewer.aspx?PhotoID="+Eval("PhotoID")+"&AlbumID="+ Eval("AlbumID") %>'> 
            <asp:Image CssClass="Timg" runat="server" ID="imPhoto" ImageUrl='<%# "ThumbNail.ashx?ImURL="+Eval("Photo") %>' />
            a>
            td>                
        ItemTemplate>             
asp:ListView>

<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
        ConnectionString="<%$ ConnectionStrings:ConnectionString %>" 
    SelectCommand="SELECT [PhotoID], [Photo], [PhotoName], [AlbumID] FROM [PhotAlbum] WHERE ([AlbumID] = @AlbumID) ORDER By [PhotoID] ASC" 
    onselected="SqlDataSource1_Selected">
        <SelectParameters>
            <asp:QueryStringParameter DefaultValue="1" Name="AlbumID" 
                QueryStringField="AlbumID" Type="Int32" />
        SelectParameters>
    asp:SqlDataSource>

同樣用SqlDataSource做爲數據綁定源。

要顯示全圖,用戶點擊縮略圖將加載全圖,帶有next和previous按鈕. 下節我們會實現這個功能。

顯示全圖:

點擊縮量圖將加載ListView中的全圖,(參考PhotoViewer.aspx) 以AlbumId 和PhotoID 做爲參數。參考圖 3. 同時還顯示next 和previous 按鈕來做相片導航。不同於其他兩個頁面,我們用代碼進行數據綁定。

在這種情況下,我們每次在ListView中顯示一張相片,如圖3所示。同樣用GroupTemplate 在ListView顯示相片。

說明:

也可以不用GroupTemplate. 用GroupTemplate,我們可以用GroupItemCount 屬性來增加每次顯示的相片的數量 .

Next 和 Previous 按鈕在DataPager中顯示. 閱讀我的文章- Paging in ListView in ASP.Net 3.5 ,瞭解更多用DataPager分頁ListView.

所以, ListView應該像這樣,

<table>
    <tr>
    <td>
        <asp:ListView ID="lvPhotoViewer" runat="server" GroupItemCount="1">
         <LayoutTemplate>                
             <table ID="groupPlaceholderContainer" runat="server" border="1">                               
                  <tr ID="groupPlaceholder" runat="server">
                  tr>
             table>                       
         LayoutTemplate>
               
         <ItemTemplate>
             <td id="Td4" align="center" style="background-color: #eeeeee;">
                    <asp:Image runat="server" ID="imPhoto" Height="450px" Width="450px" ImageUrl='<%# "~"+Eval("Photo") %>' />
                    <br />
                    <asp:Label ID="DefaultPhotIDLabel" runat="server" 
                            Text='<%# Eval("PhotoName") %>' />
             td>
        ItemTemplate>
   
         <GroupTemplate>
              <tr ID="itemPlaceholderContainer" runat="server">
                   <td ID="itemPlaceholder" runat="server">
                   td>
              tr>
        GroupTemplate>
        asp:ListView>
    td>
    tr>
    <tr>
    <td align="center">
        <asp:DataPager ID="DataPager1" runat="server" 
        PagedControlID="lvPhotoViewer" PageSize="1" 
        onprerender="DataPager1_PreRender">
        <Fields>
            <asp:NextPreviousPagerField ButtonType="Link"
            PreviousPageText="<< " NextPageText=" >>" />
         Fields>
        asp:DataPager>
    td>
    tr>
table> 

CS代碼:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        string photoID = Request.QueryString["PhotoID"];
        string albumID = Request.QueryString["AlbumID"];
        ViewState["hfAlbumID"] = albumID;
        //Get Page number by passing photo id
        int index = GetPageNumber(int.Parse(photoID), int.Parse(albumID));
        DataPager1.SetPageProperties(index, 1, true);          
    }
}
/// <summary>
/// Since the pagesize is 1 the row number can be taken as page number
/// summary>
/// <param name="PhotoID">param>
/// <param name="AlbumID">param>
/// <returns>returns>
public int GetPageNumber(int PhotoID,int AlbumID)
{
    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
    con.Open();
    SqlCommand com = new SqlCommand("SELECT PageNumber FROM (SELECT row_number() Over (order by photoid asc) AS PageNumber,photoid,Albumid "+
    " FROM PhotAlbum where Albumid=" + AlbumID.ToString() + ") As Photos where photoid=" + PhotoID.ToString() + " and Albumid=" 
    + AlbumID.ToString(), con);
    SqlDataReader dr = com.ExecuteReader();
    int pageno = 1;
    if (dr.Read())
    {
        pageno = int.Parse(dr["PageNumber"].ToString());
    }
    dr.Close();
    con.Close();
    return (pageno - 1);       
}
public DataTable GetPhoto(string query)
{
    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
    SqlDataAdapter ada = new SqlDataAdapter(query, con);
    DataTable dtEmp = new DataTable();
    ada.Fill(dtEmp);
    return dtEmp;
}   
protected void DataPager1_PreRender(object sender, EventArgs e)
{
    lvPhotoViewer.DataSource = GetPhoto("Select * from PhotAlbum where AlbumID = " + ViewState["hfAlbumID"].ToString());
    lvPhotoViewer.DataBind();
}   

既然我們每次顯示一張相片,例如 PageSize 爲1,從SqlServer 2005中獲取的page number 和 Row number 是一樣的. 所以, GetPageNumber() 方法將返回縮略圖的Row_Number() ,用來顯示ListView的特定頁.

說明:

Row_Number() 只適用於Sql Server 2005及以上版本. 我用行內查詢綁定到數據庫. 你可以用存儲過程來提高性能,以及避免sql注入攻擊。

本文代碼下載:Download Source

發佈了34 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章