=x= 🌵 Yachts 前台頁面 - Yachts - Master Page 後端功能製作。
📌 進到 Yachts 頁面後會發現,點擊遊艇型號側邊欄畫面會變動內容的包含 :
👺 從上面的拆分可以發現如果從綠色區塊來看,他在切換內容分頁時,不會變動的區塊就是紅色區塊,所以紅色區塊我們就可以製作成 Master Page,而綠色區塊則是 Content Page,但是因為區塊如果點擊遊艇型號側邊欄則會對應改變紅色跟綠色區塊,因此主版頁面的後置程式碼需要處理這些變動的對應。
<head>及<body>內的內容分別複製到 .Master 檔案中。a. 紫色底線 : 用來隱藏上方輪播相簿,若要使用可參考下一步驟說明。
b. 紅色區塊 : 輪播相簿接收區塊,使用 asp:Repeater 控制項 JavaScript 才能正確抓到。
👀 asp:Repeater 控制項用法官方參考 : Repeater 類別
👀 Eval() 用法官方參考 : DataBinder.Eval 方法
<head> 內自動產生用來接收 <head> 內容資料的控制項移至 <head> 標籤內最下方protected void Page_Init(object sender, EventArgs e)
{
    if (!IsPostBack) {
        //將型號對應 guid 存入 Session 與子頁共用
        getGuid(); //要放在 Init 不然 Content 頁會去先去抓 Session 而抓不到
    }
}
👺 用除錯模式可以發現換頁時是先讀 Content 頁,再讀 Master 頁,所以才放在 Init。
👺 執行順序 : Content 頁 Init > Master 頁 Init > Content 頁 Load > Master 頁 Load。
private void getGuid()
{
    //取得網址傳值的型號對應 GUID
    string guidStr = Request.QueryString["id"];
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT TOP 1 guid FROM Yachts";
    SqlCommand command = new SqlCommand(sql, connection);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    if (reader.Read()) {
        //如果無網址傳值就用第一筆遊艇型號的 GUID
        if (String.IsNullOrEmpty(guidStr)) {
            guidStr = reader["guid"].ToString().Trim();
        }
    }
    connection.Close();
    //將 GUID 存入 Session 供上方列表共用
    Session["guid"] = guidStr;
}
🌵 直接點 Yachts 頁會無網址傳值,直接用第一筆型號資料。
🌵 點側邊欄時會更新型號網址傳值 GUID。
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) {
        loadGallery(); //讀取並渲染上方相簿輪播
        loadLeftMenu(); //讀取並渲染左側型號邊欄
        loadTopMenu(); //讀取並渲染型號內容上方標題及分頁列
    }
}
private void loadGallery()
{
    //建立資料表存資料
    DataTable dataTable = new DataTable();
    //新增表格欄位,預設從 1 開始, 設定欄位名稱
    dataTable.Columns.AddRange(new DataColumn[1] { new DataColumn("ImageUrl") });
    //取得 Session 共用 GUID,Session 物件需轉回字串
    string guidStr = Session["guid"].ToString();
    //依 GUID 取得遊艇輪播圖片資料
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT bannerImgPathJSON FROM Yachts WHERE guid = @guidStr";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@guidStr", guidStr);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    List<ImagePath> savePathList = new List<ImagePath>();
    if (reader.Read()) {
        string loadJson = HttpUtility.HtmlDecode(reader["bannerImgPathJSON"].ToString());
        savePathList = JsonConvert.DeserializeObject<List<ImagePath>>(loadJson);
        foreach (var item in savePathList) {
            //逐一填入圖片路徑欄位值
            dataTable.Rows.Add($"upload/Images/{item.SavePath}");
        }
    }
    connection.Close();
    //輪播圖片必須用 Repeater 送不然 JavaScript 抓不到 HTML 標籤會失敗
    //設定用 Eval 綁定的輪播圖片路徑資料
    RepeaterImg.DataSource = dataTable; //設定資料來源
    RepeaterImg.DataBind(); //刷新圖片資料
}
//型號輪播圖片 JSON 資料
public class ImagePath
{
    public string SavePath { get; set; }
}
🌵 Repeater 的資料要先建立一個 DataTable 填完資料後,再指定給它。
👀 Repeater 用法參考官方 : Repeater 類別
👀 DataTable 用法參考官方 : DataTable 類別
👀 DataTable 使用方式參考 : [ASP.NET][C#][System.Data]建立/Create DataTable
private void loadLeftMenu()
{
    string urlPathStr = System.IO.Path.GetFileName(Request.PhysicalPath);
    //取得遊艇型號資料
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT * FROM Yachts";
    SqlCommand command = new SqlCommand(sql, connection);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    StringBuilder leftMenuHtml = new StringBuilder();
    while (reader.Read()) {
        string yachtModelStr = reader["yachtModel"].ToString();
        string isNewDesignStr = reader["isNewDesign"].ToString();
        string isNewBuildingStr = reader["isNewBuilding"].ToString();
        string guidStr = reader["guid"].ToString();
        string isNewStr = "";
        //依是否為新建或新設計加入標註
        if (isNewDesignStr.Equals("True")) {
            isNewStr = "(New Design)";
        }
        else if (isNewBuildingStr.Equals("True")) {
            isNewStr = "(New Building)";
        }
        leftMenuHtml.Append($"<li><a href='{urlPathStr}?id={guidStr}'>{yachtModelStr} {isNewStr}</a></li>");
    }
    connection.Close();
    //渲染左側遊艇型號選單
    LeftMenuHtml.Text = leftMenuHtml.ToString();
}
🌵 依型號標註判斷類型加入文字標示於型號後方。
👺 連結位置要配合目前所在的內容分頁設定,於 Video 頁製作時,會建立如果跳轉到沒有影片連結的型號,會自動跳轉成型號的 Overview 內容分頁。
private void loadTopMenu()
{
    //取得 Session 共用 GUID,Session 物件需轉回字串
    string guidStr = Session["guid"].ToString();
    //依 GUID 取得遊艇資料
    List<RowData> saveRowList = new List<RowData>();
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT * FROM Yachts WHERE guid = @guidStr";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@guidStr", guidStr);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    StringBuilder topMenuHtmlStr = new StringBuilder();
    StringBuilder dimensionsTableHtmlStr = new StringBuilder();
    if (reader.Read()) {
        string yachtModelStr = reader["yachtModel"].ToString();
        string contentHtmlStr = HttpUtility.HtmlDecode(reader["overviewContentHtml"].ToString());
        string loadJson = HttpUtility.HtmlDecode(reader["overviewDimensionsJSON"].ToString());
        string dimensionsImgPathStr = reader["overviewDimensionsImgPath"].ToString();
        string downloadsFilePathStr = reader["overviewDownloadsFilePath"].ToString();
        //加入渲染型號內容上方分類連結列表
        topMenuHtmlStr.Append($"<li><a class='menu_yli01' href='Yachts_OverView.aspx?id={guidStr}' >OverView</a></li>");
        topMenuHtmlStr.Append($"<li><a class='menu_yli02' href='Yachts_Layout.aspx?id={guidStr}' >Layout & deck plan</a></li>");
        topMenuHtmlStr.Append($"<li><a class='menu_yli03' href='Yachts_Specification.aspx?id={guidStr}' >Specification</a></li>");
        //加入渲染型號內容上方分類連結列表 Video 分頁標籤,有存影片連結網址才渲染
        saveRowList = JsonConvert.DeserializeObject<List<RowData>>(loadJson);
        if (!String.IsNullOrEmpty(saveRowList[0].SaveValue)) {
            topMenuHtmlStr.Append($"<li><a class='menu_yli04' href='Yachts_Video.aspx?id={guidStr}' >Video</a></li>");
        }
        //渲染畫面
        //渲染上方小連結
        LabLink.InnerText = yachtModelStr;
        //渲染標題
        LabTitle.InnerText = yachtModelStr;
        //渲染型號內容上方分類連結列表
        TopMenuLinkHtml.Text = topMenuHtmlStr.ToString();
    }
    connection.Close();
}
//表格欄位 JSON 資料
public class RowData
{
    public string SaveItem { get; set; }
    public string SaveValue { get; set; }
}
📢 今天的內容可以複習如何設定主版頁面,之前是在後台使用,這次是前台頁面使用,這樣可以大量減少重複的程式碼內容,所有遊艇型號內容分頁共用相同邏輯的主版頁面,裡面側邊欄會依照目前所在內容分頁而改變連結網址,是根據原始網站的模式,也可以都導回到各個型號的 Overview 頁面會比較簡單,但使用者操作體驗較差,需要多做一次點選分頁內容,才能比對不同型號的相同內容。