iT邦幫忙

2021 iThome 鐵人賽

DAY 21
2
Modern Web

ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#系列 第 21

Day 21 - 依 Home 前台頁面分析拆解後,逐步建立後台功能 - GridView 事件應用 - ASP.NET Web Forms C#

=x= 🌵 建立 Yacht Manager - Content Page 後台頁面。


Home 前台頁面分析 :

https://ithelp.ithome.com.tw/upload/images/20211005/20139487H6FksMwZQZ.jpg

https://ithelp.ithome.com.tw/upload/images/20211005/20139487zIJxRskx6s.jpg

📌 在 Home 頁面的輪播大圖照片,可以知道每個遊艇型號都會有一張圖,圖片右下角會對應更換遊艇型號,而左上角會對應遊艇型號是新建造就出現紅色標籤,遊艇型號可從 Yachts 頁面側邊欄看到全部遊艇型號特殊註記,點擊側邊欄會發現如新聞列表頁的模式,會在網址列出現網址傳值是使用 GUID 隨機碼來對應資料;另外,在首頁的輪播大圖下方有 3 組新聞圖卡,查看原始碼可以發現有個 Top 標籤,是用來加註焦點新聞的圖標,效果可以參考上圖右下區塊。

🌵 遊艇型號是新設計並沒有配合對應的圖標,可以自行拿新建造的圖片修圖後使用。

🌵 新聞圖卡的 Top 標籤,可以將 HTML 裡的 style="display: none" 拿掉就能看到效果。



Yacht Manager 後台頁面介紹 :

https://ithelp.ithome.com.tw/upload/images/20211005/20139487fuwmdBqg86.jpg

  • 🧠 上半部 - 多圖上傳相簿功能並添加下拉式選單配合切換

  • 🧠 下半部 - 左側含勾選項目及2個輸入框的遊艇型號添加區,右側為遊艇型號列表



Yacht Manager 後台實作 :

1. 建立遊艇型號資料表,紅色區域為首頁關聯相關資料

https://ithelp.ithome.com.tw/upload/images/20211005/20139487qII6Sir6ky.jpg

  • 🌵 相關預設值請參考之前文章建立,下半部資料會在之後文章介紹。


2. 上半部 - 多圖上傳相簿功能並添加下拉式選單配合切換介面設計參考如下

<div class="input-group my-3">
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" DataSourceID="SqlDataSource1" DataTextField="yachtModel" DataValueField="id" Width="50%" Font-Bold="True" class="btn btn-outline-primary dropdown-toggle" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"></asp:DropDownList>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TayanaYachtConnectionString %>" SelectCommand="SELECT [yachtModel], [id] FROM [Yachts]"></asp:SqlDataSource>
    <asp:FileUpload ID="imageUpload" runat="server" class="btn btn-outline-primary btn-block" AllowMultiple="True" />
    <asp:Button ID="UploadBtn" runat="server" Text="Upload" class="btn btn-primary" OnClick="UploadBtn_Click" />
</div>
<hr />
<h6>Banner Image List :</h6>
<h6><span class="badge badge-pill badge-success text-dark">* The first image will be the home page banner !</span></h6>
<h6>Step1. To upload one image to be the home page banner.</h6>
<h6>Step2. Then upload other images.</h6>
<asp:RadioButtonList ID="RadioButtonList" runat="server" class="my-3 mx-auto" AutoPostBack="True" CellPadding="10" RepeatColumns="5" RepeatDirection="Horizontal" OnSelectedIndexChanged="RadioButtonListH_SelectedIndexChanged" ></asp:RadioButtonList>
<asp:Button ID="DelImageBtn" runat="server" Text="Delete Image" type="button" class="btn btn-danger btn-sm" OnClientClick="return confirm('Are you sure you want to delete?')" Visible="False" OnClick="DelHImageBtn_Click" />
  • 👀 DropDownList 控制項資料設定請參考 Day9 文章介紹。


3. 下半部 - 左側含勾選項目及2個輸入框的遊艇型號添加區介面設計參考如下

<asp:CheckBox ID="CBoxNewDesign" runat="server" Text="NewDesign" Width="50%" />
<asp:CheckBox ID="CBoxNewBuilding" runat="server" Text="NewBuilding" Width="50%" />
<div class="input-group mb-3">
    <asp:TextBox ID="TBoxAddYachtModel" runat="server" type="text" class="form-control" placeholder="Model" Width="30%" ></asp:TextBox>
    <asp:TextBox ID="TBoxAddYachtLength" runat="server" type="text" class="form-control" placeholder="Length" ></asp:TextBox>
    <div class="input-group-append">
        <asp:Button ID="BtnAddYacht" runat="server" Text="Add" class="btn btn-outline-primary btn-block" OnClick="BtnAddYacht_Click" />
    </div>
</div>
  • 🌵 遊艇型號的數字其實是長度英呎的含意,是行業的慣性用語。

  • 🌵 分開輸入是因為其它頁面會取出後面的數值,及控制遊艇型號出現時的排版效果。


4. 下半部 - 右側為遊艇型號列表介面設計參考如下

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="id" DataSourceID="SqlDataSource2" BackColor="White" BorderColor="#CCCCCC" BorderStyle="None" BorderWidth="1px" CellPadding="3" Width="100%" OnRowDeleted="DeletedModel" OnRowUpdated="UpdatedModel" OnRowDeleting="DeletingModel">
  <Columns>
      <asp:CommandField ButtonType="Button" CancelText="Cancel" DeleteText="Delete" EditText="Edit" HeaderText="Edit" InsertText="Insert" NewText="New" SelectText="Select" ShowEditButton="True"  ControlStyle-CssClass='btn btn-primary btn-block' ControlStyle-BorderColor="#66CCFF" ControlStyle-BorderStyle="Solid" ControlStyle-BorderWidth="1px" ControlStyle-ForeColor="White" >
      <ControlStyle BorderColor="#66CCFF" BorderWidth="1px" BorderStyle="Solid" CssClass="btn btn-primary btn-block" ForeColor="White"></ControlStyle>
      </asp:CommandField>
      <asp:BoundField DataField="id" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="id" />
      <asp:BoundField DataField="yachtModel" HeaderText="Yacht Model" SortExpression="yachtModel" />
      <asp:CheckBoxField DataField="isNewDesign" HeaderText="New Design" SortExpression="isNewDesign" />
      <asp:CheckBoxField DataField="isNewBuilding" HeaderText="New Building" SortExpression="isNewBuilding" />
      <asp:BoundField DataField="initData" HeaderText="Creation Date" SortExpression="initData" InsertVisible="False" ReadOnly="True" />
      <asp:TemplateField HeaderText="Delete" ShowHeader="False">
          <ItemTemplate>
              <asp:LinkButton ID="BtnDeleteCountry" runat="server" CommandName="Delete" Text="Delete" OnClientClick="return confirm('Are you sure you want to delete?')" CausesValidation="False"></asp:LinkButton>
          </ItemTemplate>
          <ControlStyle BorderColor="#66CCFF" BorderStyle="Solid" BorderWidth="1px" CssClass="btn btn-danger btn-block" ForeColor="White" />
      </asp:TemplateField>
  </Columns>
  <FooterStyle BackColor="White" ForeColor="#000066" />
  <HeaderStyle BackColor="#006699" Font-Bold="True" ForeColor="White" />
  <PagerStyle BackColor="White" ForeColor="#000066" HorizontalAlign="Left" />
  <RowStyle ForeColor="#000066" />
  <SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
  <SortedAscendingCellStyle BackColor="#F1F1F1" />
  <SortedAscendingHeaderStyle BackColor="#007DBB" />
  <SortedDescendingCellStyle BackColor="#CAC9C9" />
  <SortedDescendingHeaderStyle BackColor="#00547E" />
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:TayanaYachtConnectionString %>" SelectCommand="SELECT [id], [yachtModel], [isNewDesign], [isNewBuilding], [initData] FROM [Yachts]" DeleteCommand="DELETE FROM [Specification] WHERE [yachtModel_ID] = @id; DELETE FROM [Yachts] WHERE [id] = @id" UpdateCommand="UPDATE [Yachts] SET [yachtModel] = @yachtModel, [isNewDesign] = @isNewDesign, [isNewBuilding] = @isNewBuilding WHERE [id] = @id">
  <DeleteParameters>
      <asp:Parameter Name="id" Type="Int32" />
  </DeleteParameters>
  <UpdateParameters>
      <asp:Parameter Name="isNewBuilding" Type="Boolean" />
      <asp:Parameter Name="isNewDesign" Type="Boolean" />
      <asp:Parameter Name="yachtModel" Type="String" />
      <asp:Parameter Name="id" Type="Int32" />
  </UpdateParameters>
</asp:SqlDataSource>
  • 🌵 OnRowDeleting 事件用來在刪除的同時,先取得型號並用來刪除相關圖檔及資料。

  • 🌵 Command 加入同步刪除關聯資料的語法,可在製作後續頁面時回頭修改。

  • 🌵 Parameter 需注意 CheckBoxField 的 Type 是 Boolean 類型。

  • 👀 GridView 事件參考官網資料 : GridView 類別


5. 在頁面後置程式碼加入遊艇型號 Add 按鈕 OnClick 事件程式碼如下

protected void BtnAddYacht_Click(object sender, EventArgs e)
{
    //插入空格區隔文字跟數字 (頁面細項標題會用到)
    string yachtModelStr = TBoxAddYachtModel.Text + " " + TBoxAddYachtLength.Text;
    //產生 GUID 隨機碼 + 時間2位秒數 (加強避免重複)
    DateTime nowTime = DateTime.Now;
    string nowSec = nowTime.ToString("ff");
    string guidStr = Guid.NewGuid().ToString().Trim() + nowSec;
    //取得勾選項目
    string isNewDesign = CBoxNewDesign.Checked.ToString();
    string isNewBuilding = CBoxNewBuilding.Checked.ToString();

    //插入遊艇型號基本資料
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "INSERT INTO Yachts (yachtModel, isNewDesign, isNewBuilding, guid) VALUES (@yachtModelStr, @isNewDesign, @isNewBuilding, @guidStr)";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@yachtModelStr", yachtModelStr);
    command.Parameters.AddWithValue("@isNewDesign", isNewDesign);
    command.Parameters.AddWithValue("@isNewBuilding", isNewBuilding);
    command.Parameters.AddWithValue("@guidStr", guidStr);
    connection.Open();
    command.ExecuteNonQuery();
    connection.Close();

    //畫面渲染
    DropDownList1.DataBind();
    GridView1.DataBind();
    TBoxAddYachtModel.Text = "";
    TBoxAddYachtLength.Text = "";
    CBoxNewDesign.Checked = false;
    CBoxNewBuilding.Checked = false;
    DropDownList1.SelectedValue = yachtModelStr; //設定下拉選單選取項為新增項
    RadioButtonList.Items.Clear(); //新添加型號還沒有任何圖片,記得要清空畫面
}


6. 加入遊艇型號列表的 Delete 按鈕 OnRowDeleting 事件程式碼如下

protected void DeletingModel(object sender, GridViewDeleteEventArgs e)
{
    //在刪除狀態下先取得刪除項的索引鍵欄位值
    string idStr = "";
    foreach (DictionaryEntry entry in e.Keys) {
        idStr = entry.Value.ToString();
    }

    //取出刪除的遊艇型號的組圖資料
    string savePath = Server.MapPath("~/Tayanahtml/upload/Images/");
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sqlBannerImg = "SELECT bannerImgPathJSON FROM Yachts WHERE id = @idStr";
    SqlCommand command = new SqlCommand(sqlBannerImg, connection);
    command.Parameters.AddWithValue("@idStr", idStr);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    if (reader.Read()) {
        string loadJson = HttpUtility.HtmlDecode(reader["bannerImgPathJSON"].ToString());
        //反序列化JSON格式
        savePathList = JsonConvert.DeserializeObject<List<ImagePath>>(loadJson);
    }
    connection.Close();
    //刪除組圖實際圖檔
    for (int i = 0; i < savePathList.Count; i++) {
        File.Delete(savePath + savePathList[i].SavePath);
    }

        //以下為製作後續頁面後需執行的程式碼
    //取出刪除的遊艇型號的 Layout 組圖資料
    string sqlLayoutImg = "SELECT layoutDeckPlanImgPathJSON FROM Yachts WHERE id = @idStr";
    SqlCommand command2 = new SqlCommand(sqlLayoutImg, connection);
    command2.Parameters.AddWithValue("@idStr", idStr);
    connection.Open();
    SqlDataReader reader2 = command2.ExecuteReader();
    if (reader2.Read()) {
        string loadJson = HttpUtility.HtmlDecode(reader2["layoutDeckPlanImgPathJSON"].ToString());
        //反序列化JSON格式
        savePathList = JsonConvert.DeserializeObject<List<ImagePath>>(loadJson);
    }
    connection.Close();
    //刪除組圖實際圖檔
    for (int i = 0; i < savePathList.Count; i++) {
        File.Delete(savePath + savePathList[i].SavePath);
    }

    //取出刪除的遊艇型號的 overview 規格圖片資料
    string sqlDimImg = "SELECT overviewDimensionsImgPath FROM Yachts WHERE id = @idStr";
    SqlCommand command3 = new SqlCommand(sqlDimImg, connection);
    command3.Parameters.AddWithValue("@idStr", idStr);
    connection.Open();
    SqlDataReader reader3 = command3.ExecuteReader();
    if (reader3.Read()) {
        string imgPath = reader3["overviewDimensionsImgPath"].ToString();
        //刪除實際圖檔
        if (!String.IsNullOrWhiteSpace(imgPath)) {
            File.Delete(savePath + imgPath);
        }
    }
    connection.Close();

    //取出刪除的遊艇型號的 overview 的 PDF 檔案資料
    string sqlPDF = "SELECT overviewDownloadsFilePath FROM Yachts WHERE id = @idStr";
    SqlCommand command4 = new SqlCommand(sqlPDF, connection);
    command4.Parameters.AddWithValue("@idStr", idStr);
    connection.Open();
    SqlDataReader reader4 = command4.ExecuteReader();
    if (reader4.Read()) {
        string imgPath = reader4["overviewDownloadsFilePath"].ToString();
        //刪除實際圖檔
        if (!String.IsNullOrWhiteSpace(imgPath)) {
            File.Delete(savePath + imgPath);
        }
    }
    connection.Close();
}
  • 🌵 刪除型號 Layout 組圖之後相關刪除圖檔程式碼,可於之後頁面製作完成後再添加。


7. 在 Page_Load 事件加入以下程式碼載入相簿圖片

//宣告 List 方便用 Add 依序添加圖檔資料
private List<ImagePath> savePathList = new List<ImagePath>();
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) {
        DropDownList1.DataBind(); //先綁定,圖片才能取到型號
        loadImageList();
    }
}


8. 參考相簿功能文章建立相簿功能邏輯,loadImageList(); 為相簿功能中的讀取圖片功能

private void loadImageList()
{
    //取得下拉選單選取值
    string selModel_id = DropDownList1.SelectedValue;
    //連線資料庫取得首頁輪播圖資料
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sqlLoad = "SELECT bannerImgPathJSON FROM Yachts WHERE id = @selModel_id";
    SqlCommand command = new SqlCommand(sqlLoad, connection);
    command.Parameters.AddWithValue("@selModel_id", selModel_id);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    if (reader.Read()) {
        string loadJson = HttpUtility.HtmlDecode(reader["bannerImgPathJSON"].ToString());
        //反序列化JSON格式
        savePathList = JsonConvert.DeserializeObject<List<ImagePath>>(loadJson);
    }
    connection.Close();
    if (savePathList?.Count > 0) {
        //預設第一張上傳的圖片為該遊艇型號首頁圖片
        bool firstCheck = true;
        foreach (var item in savePathList) {
            if (firstCheck) {
                //替首張圖片加上醒目色彩邊框
                ListItem listItem = new ListItem($"<img src='/Tayanahtml/upload/Images/{item.SavePath}' alt='thumbnail' class='img-thumbnail bg-success' width='200px'/>", item.SavePath);
                RadioButtonList.Items.Add(listItem);
                firstCheck = false;
            }
            else {
                ListItem listItem = new ListItem($"<img src='/Tayanahtml/upload/Images/{item.SavePath}' alt='thumbnail' class='img-thumbnail' width='200px'/>", item.SavePath);
                RadioButtonList.Items.Add(listItem);
            }
        }
    }
    DelImageBtn.Visible = false; //刪除鈕有選擇圖片時才顯示
}
  • 🌵 SQL 語法的 WHERE 限制條件記得要改成下拉選單所選取的值,取值方法如下 : DropDownList1.SelectedValue;

  • 👺 相簿管理相關功能請參考 Day12 文章,完成完整功能建立。


9. 加入遊艇型號列表的 Delete 按鈕 OnRowDeleted 事件程式碼如下

protected void DeletedModel(object sender, GridViewDeletedEventArgs e)
{
    RadioButtonList.Items.Clear(); //清空圖片選項
    DropDownList1.DataBind(); //刷新下拉選單
    loadImageList(); //取得圖片選項
}


10. 加入遊艇型號列表的 Updated 按鈕 OnRowUpdated 事件程式碼如下

protected void UpdatedModel(object sender, GridViewUpdatedEventArgs e)
{
    DropDownList1.DataBind(); //刷新下拉選單
}


11. 加入遊艇型號下拉選單選擇改變時的 OnSelectedIndexChanged 事件程式碼如下

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    RadioButtonList.Items.Clear(); //清空圖片選項
    loadImageList(); //取得圖片選項
}


12. 模擬頁面後測試功能,Yacht Manager 後台完成 ~



本日總結 :

📢 本日實作算是之前實作的整合版,只要整合之前實作過的功能就可以完成,需要注意的是刪除遊艇型號時,要一併刪除型號相關的資料包含時計圖檔,而為了在刪除型號時一併刪除其它資料,所以要先取得刪除的遊艇型號,但如果取型號在一般的 OnRowDeleted 執行時,因為這時候型號已被刪除所以無法取得,在查了微軟官網的 GridView 事件後,發現可以把取型號的行為在刪除進行中的 OnRowDeleting 事件裡執行,並且執行相關資料刪除的行為,算是新的知識點。

  • 明日將介紹製作 Home Page - 輪播圖後端的相關細節。

上一篇
Day 20 - 將 NEWS 後台儲存資料提取後,送至前台渲染畫面 (下) - News View Page InnerText 應用 - ASP.NET Web Forms C#
下一篇
Day 22 - 將 Yacht Manager 後台儲存資料提取後,送至前台渲染首頁 Home 頁面 (上) - 輪播圖區 - ASP.NET Web Forms C#
系列文
ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言