CSS&javascript 產品分頁&購物車清單

這是接續購物產品列表的部份
之前透過DataList產生出全部的產品列表

css&javascript 連製資料庫撈出圖片(datalist)

這有個滿大的問題就是…他沒有分頁
沒錯,抓出來所有的資料都會在同一頁
實在滿痛的,中文北風只有77個產品還好一點
如果今天有7千個呢?光圖片就很耗流量了

所以今天要實現將抓出來的產品分頁,並接著完成購物車的事件




首先,必須在SQL Server中先建立好預存程序
並賦予可以使用PROCEDURE的權限:

use 中文北風
go

--sql 2012前 用cte-----------------------------------------------------
CREATE PROCEDURE 產品分頁1 @page INT
AS
 DECLARE @start INT
 DECLARE @end INT
 SET @start = (@page-1)*10+1
 SET @end = @page*10;

 WITH temp
 as
 (
  SELECT 產品資料.產品編號, 產品資料.產品, 供應商.供應商, 產品類別.類別名稱,
      產品資料.單位數量, 產品資料.單價, 產品資料.庫存量
     ,ROW_NUMBER() OVER(ORDER BY 產品編號) AS 序號
  FROM 供應商 INNER JOIN 產品資料 ON 供應商.供應商編號 = 產品資料.供應商編號
     INNER JOIN 產品類別 ON 產品資料.類別編號 = 產品類別.類別編號
 )
 SELECT 產品編號,產品,供應商,類別名稱,單位數量,單價,庫存量
 FROM temp
 WHERE 序號 BETWEEN @start AND @end
GO
--sql 2012後才有的offset------------------------------------------------------
CREATE PROCEDURE 產品分頁2 @page INT
AS
DECLARE @skip INT
SET @skip = (@page-1)*10;
 SELECT 產品資料.產品編號, 產品資料.產品, 供應商.供應商, 產品類別.類別名稱,
     產品資料.單位數量, 產品資料.單價, 產品資料.庫存量
 FROM 供應商 INNER JOIN 產品資料 ON 供應商.供應商編號 = 產品資料.供應商編號
       INNER JOIN 產品類別 ON 產品資料.類別編號 = 產品類別.類別編號
 ORDER BY 產品編號 OFFSET @skip ROWS FETCH NEXT 10 ROWS ONLY

--由於原本sqluser 沒有執行proc的權限,所以要賦予給他
GRANT EXECUTE TO SQLuser


以上如果不懂可以參考之前做過SQL Server的筆記:
SQL Server 資料庫的權限設定
SQL Server 一般資料表運算式(CTE)
SQL Server EXECUTE指令及STORED PROCEDURE
SQL Server Row相關的函數

產品分頁1產品分頁2 都是一樣的
會跟據使用者選擇的頁數,回傳該頁數的結果
例如點選1,會回傳1~10筆的產品

=============================================================================


接著,我們要對NWDB資料庫繫結的類別庫進行修改
這邊會執行2個部份:
  1. 要求資料庫回傳產品的總數,如此才可以做分頁
  2. 當使用者點選購物車,會去資料庫找出產品資料並加入購物清單列表

先修改介面IProduct.cs

public interface IProduct
{
    DataTable SearchProduct();//這裡不做,可以不理
    int ProductCount();
    Dictionary<string object=""> GetProductInfoId(int productId);
}

再修改實作ImpIProduct.cs

public class ImpIProduct:IProduct
{
        
    private SqlConnection cnn;

    public ImpIProduct(SqlConnection cnn)
    {
        this.cnn = cnn;
    }

    //-----------------------------------------------------------------
    #region 尋找產品
    public DataTable SearchProduct()
    {
        //先不做,之後進入MVC再做
        return null;
    }
    #endregion 尋找產品

    //-----------------------------------------------------------------
    #region 產品總數
    public int ProductCount()
    {
        SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM 產品資料", cnn);
        cnn.Open();
        int ProductCount =(int) cmd.ExecuteScalar();
        cmd.Dispose();
        cnn.Close();
        return ProductCount;
    }
    #endregion 產品總數

    //-----------------------------------------------------------------
    #region 購物車加入
    public Dictionary<string, object> GetProductInfoId(int productId)
    {
        SqlCommand cmd = new SqlCommand("SELECT 產品,單價 FROM 產品資料 WHERE 產品編號 = @Pid", cnn);
        cmd.Parameters.Add("@Pid", SqlDbType.Int).Value = productId;
            
        Dictionary<string, object> result = null;
        cnn.Open();

        SqlDataReader mydr = cmd.ExecuteReader();
        //如果有資料
        if (mydr.HasRows)
        {
            result = new Dictionary<string,object>();
            mydr.Read();
            result.Add("產品編號",productId);
            result.Add("產品名稱", mydr[0]);
            result.Add("單價", mydr[1]);
        }

        cmd.Dispose();
        cnn.Close();
        return result;
    }
    #endregion 購物車加入
}

最後修改NWDB.cs中「#region 產品」裡的方法

//引入實作的方法
#region 產品
public DataTable SearchProduct()
{
    return ip.SearchProduct();
}
public int ProductCount()
{
    return ip.ProductCount();
}
public Dictionary GetProductInfoId(int productId)
{
    return ip.GetProductInfoId(productId);
}
#endregion 產品

=============================================================================


資料庫是前置作業,設定完成後,接著網頁介面aspx撰寫:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Data3.aspx.cs" Inherits="WebPractice.Data.data3" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style type="text/css">
        //使整個產品資料表置中
        #ResultDiv {
            margin-left:auto;
            margin-right:auto;
            width:800px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">  
        <div id="ResultDiv">  
        <asp:DataList ID="DataList1" runat="server" DataKeyField="產品編號" DataSourceID="SqlDataSource1" Width="700px">
            <ItemTemplate>
                <table cellpadding="5" cellspacing="0" width="100%">
                    <tr>
                        <td width="150"><img src="/Tools/GetProductImage.ashx?pid=<%# Eval("產品編號") %>" /></td>
                        <td>
                            <table cellpadding="10" cellspacing="0" class="auto-style1">
                                <tr>
                                    <td colspan="4"><asp:Label ID="產品Label" runat="server" Text='<%# Eval("產品") %>' /></td>
                                </tr>
                                <tr>
                                    <td align="right" width="80">產品編號:</td>
                                    <td><asp:Label ID="產品編號Label" runat="server" Text='<%# Eval("產品編號") %>' /></td>
                                    <td align="right" width="80">單位數量:</td>
                                    <td><asp:Label ID="單位數量Label" runat="server" Text='<%# Eval("單位數量") %>' /></td>
                                </tr>
                                <tr>
                                    <td align="right" width="80">單價:</td>
                                    <td>
                                        <asp:Label ID="單價Label" runat="server" Text='<%# Eval("單價") %>' />
                                    </td>
                                    <td align="right" width="80">供應商:</td>
                                    <td>
                                        <asp:Label ID="供應商Label" runat="server" Text='<%# Eval("供應商") %>' />
                                    </td>
                                </tr>
                                <tr>
                                    <td align="right" width="80">類別名稱:</td>
                                    <td>
                                        <asp:Label ID="類別名稱Label" runat="server" Text='<%# Eval("類別名稱") %>' />
                                    </td>
                                    <td align="right" width="80">庫存量:</td>
                                    <td>
                                        <asp:Label ID="庫存量Label" runat="server" Text='<%# Eval("庫存量") %>' />
                                    </td>
                                </tr>
                                <tr>

                                    <!-- ============================購物車圖放入 ============================-->
                                    <!-- 放入購物車圖,並設定連結pid = 產品的編號 -->  
                                    <td colspan="4"><a href="AddToCart.aspx?pid=<%# Eval("產品編號") %>"><img src="/images/Shapping_cart.png" title="買了他!" border="0"/></a></td>



                                    <td> </td>
                                    <td> </td>
                                    <td> </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                </table>
            </ItemTemplate>
        </asp:DataList>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:中文北風ConnectionString %>" SelectCommand="產品分頁1" SelectCommandType="StoredProcedure">
            <SelectParameters>
                <asp:QueryStringParameter DefaultValue="1" Name="Page" QueryStringField="p" Type="Int32" />
            </SelectParameters>
        </asp:SqlDataSource>
        <p style="text-align:center">
        
        <!-- ===========================Literal放入 ============================-->
        <!-- 程式執行分頁行為 --> 
        <asp:Literal ID="PageLiteral" runat="server"></asp:Literal></p>
        </div>     
    </form>
</body>
</html>



看起來很複雜,其實是aspx元件DataList拉一拉改改配置
並在最下面放個Literal,會利用程式碼來實現變身的行為
接著就是網頁裡的的程式碼:

public partial class data3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        int currentPage = 0;

        //如果TryParse「不」成功,回傳第1頁,成功就out currentPage
        if(!int.TryParse(Request.QueryString["p"] ,out currentPage))
            currentPage =1;

        //繫結資料庫
        NWDB.NWDB nwdb = new NWDB.NWDB();
        NWDB.IProduct ip = new NWDB.ImpIProduct(nwdb.Connection);
        nwdb.SetProduct(ip);
        int productcount = nwdb.ProductCount();

        //總頁數,Ceiling是無條件進位,或是回傳大於或等於指定數值運算式的最小整數。
        int totalPage = (int)Math.Ceiling(productcount / 10.0);

        StringBuilder sb = new StringBuilder();
        for(int i = 1 ; i <= totalPage; i++)
        {
            if (i == currentPage)
                sb.Append(String.Format("{0}&nbsp;&nbsp;", i));
            else
                sb.Append(String.Format("<a href=\"Data3.aspx?p={0}\">{0}</a>&nbsp;&nbsp;", i));
        }
        //將PageLiteral變身成頁碼
        PageLiteral.Text = sb.ToString();
    }
}


=============================================================================

以上即完成分頁,最後就是購物清單
在網頁撰寫的部份,每個產品都已經放入了購物車圖
並設定連結為:<a href="AddToCart.aspx?pid=<%# Eval("產品編號") %>">

就是會傳該產品編號給 AddToCart.aspx 這個網頁
在這個網頁介面其實只拉出了一個GridView元件
所有清單的增加都是用後面的AddToCart.aspx.cs在做事:

protected void Page_Load(object sender, EventArgs e)
{
    int productId = 0;
    if (!int.TryParse(Request.QueryString["Pid"], out productId))
        Response.Redirect("Data3.aspx");

    //設定一個空的Datatable
    DataView dv;

    //如果沒買過
    if (Session["Cart"] == null)
    {
        DataTable tt = new DataTable();
        tt.Columns.Add("產品編號", Type.GetType("System.Int32"));
        tt.Columns.Add("產品名稱", Type.GetType("System.String"));
        tt.Columns.Add("單價", Type.GetType("System.Double"));
        tt.Columns.Add("數量", Type.GetType("System.Int32"));
        tt.Columns.Add("金額", Type.GetType("System.Int32"), "單價*數量");
        //放入datatable
        dv = tt.DefaultView;
    }
    else
    {
        dv =(DataView)Session["Cart"];
    }

    //要先排列清單才可抓出沒買過的產品
    dv.Sort = "產品編號 ASC";
    //找出傳過來的值,是否有在購買列表中
    int index = dv.Find(productId);
    //如果找不到index會是-1,小於零
    if (index < 0)
    {
        DataTable ttt = dv.Table;
        DataRow rr = ttt.NewRow();
        NWDB.NWDB mydb = new NWDB.NWDB();
        NWDB.IProduct ip = new NWDB.ImpIProduct(mydb.Connection);
        mydb.SetProduct(ip);
        //將網頁傳來的productId放入nwdb中的查找方法
        Dictionary<string object> getResult = mydb.GetProductInfoId(productId);
        //如果資料庫中沒有這個產品,就跳轉回產品清單
        if (getResult == null) Response.Redirect("Data3.aspx");

        rr["產品編號"] = getResult["產品編號"];
        rr["產品名稱"] = getResult["產品名稱"];
        rr["單價"] = getResult["單價"];
        rr["數量"] = 1;

        ttt.Rows.Add(rr);
    }
    else
    {
        //找出dv列中,index那一列,「數量」那一格,找出後+1
        dv[index]["數量"] =(int) dv[index]["數量"] + 1;
    }
    //寫回Session,如此才會增加一筆
    Session["Cart"] = dv;

    GridView1.DataSource = dv;
    GridView1.DataBind();
}


到此,完成產品分頁及購物車採買的事件
寫起來落落長,其實真的在寫還好懂的
aspx到此真的告一段落,開始進入MVC的世界吧!

留言

熱門文章