Views: 19
前面已經做好報名功能,這邊要開始做學員資料管理Member/Manage.aspx
資料管理頁包含哪些功能
- 列表
- 欄位
- 分頁/一頁幾筆/目前頁數
- 排序
- 列表
- 總筆數
- 勾選(批次刪除或做特殊處理)
- 新增/修改/刪除
- 搜尋(含Filter)
- 匯出Excel
- 匯入Excel
- 包含匯入Sample下載
- 統計報表
- 列印
整套資料輸入輸出與查詢做起來大概有這麼多大項,然後雖然項目很多,但程式設計有個原則是沒在需求上的就不用做,每多做一個功能對專案開發上就是成本,成本就會減少公司的收入。
在來GridView是個蠻強大的工具(但效率不好),可以在上面把欄位、分頁、排序、勾選那些都做好,但缺點也是你一但脫離這麼方便的工具,學習門檻就會相當高。
思路
- 先建立
Member/Manage.aspx
Manage.aspx
加入GridView
Manage.aspx.cs
加入讀取功能Manage.aspx
的GridView
加入編輯 刪除
Manage.aspx
加入編輯/刪除
雖然上面一小節我列了很多,但這些功能是慢慢往上疊上去的,程式上先做個可以動的小雛形,再修成需要的模樣。
建立Member/Manage.aspx
在Member資料夾加入>使用主版頁面的Webform >加入Manage.aspx
這是後台的頁面,所以選的是Admin/Admin.Master
然後按下確定
Manage.aspx 加入Grid
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin/Admin.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="PartyRegister.Admin.Member.Manage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>學員管理</h1>
<asp:GridView runat="server" ID="gvList">
</asp:GridView>
</asp:Content>
一般來說GridView
普遍都會簡稱為gv
,我待過大部分公司的老專案都這樣做,所以在這邊把列表稱為gvList
。
大家可能會想問,為什麼不使用設計工具就好?
- 敲鍵盤比較快
- 程式可以直接貼給ChatGpt之類的AI直接除錯
- 敲程式比較可以知道自己做了些什麼
Manage.aspx.cs 加入讀取功能
這邊要分幾段
- 加入連線字串
connectionString
- 加入加入讀取的程式
BindData()
- 在
Page_Load
加入呼叫BindData()
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace PartyRegister.Admin.Member
{
public partial class Manage : System.Web.UI.Page
{
/// <summary>
/// 連線字串
/// </summary>
private readonly string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
//判斷頁面是第一次載入時才更新
if(!IsPostBack)
{
BindData();
}
}
/// <summary>
/// GridView 讀取資料表
/// </summary>
private void BindData()
{
string sql = "SELECT * FROM Member";
// 取得資料
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql,conn))
{
//寫法1:使用DataAdapter,資料不做後續處理的話用這個最快
//很多人用這個都是先在SQL語法上將資料處理成乾淨的資料,在讀入
var reader = cmd.ExecuteReader();
gvList.DataSource = reader;
gvList.DataBind();
// 寫法2: 使用 DataTable,通常用在讀取後要處理資料內容
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
//通常Fill後資料已經由SQL讀入Server端了
//這邊後續會在C#內對DataTable做一些處理,例如統計,資料格式轉換等
gvList.DataSource = dt;
gvList.DataBind();
// 寫法3: 使用 DataSet,通常用在讀取會同時返回很多張資料表
DataSet ds = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(ds);
}
gvList.DataSource = ds;
gvList.DataBind();
}
}
}
}
}
這邊我提供三種很常見的GridView
綁定資料的寫法,也把註解寫上去了,我生涯上最常見的是DataTable
> DataReader
> DataSet
,然後無論你用哪一種,這類讀取資料的方式都稱為弱型別,意思是讀取進來的資料不去定義資料格式,讓GriveView自己判斷。
寫法 | 優點 | 缺點 |
---|---|---|
DataReader | 效能高、記憶體消耗低、快速前進式讀取 | 必須保持連線、無法隨機存取、綁定功能受限 |
DataTable (最常見) | 支援離線操作、隨機存取、適合單表操作 | 效能略遜於 DataReader、大量資料時記憶體負擔較高 |
DataSet (實際上包含多個DataTable) | 支援多表操作、建立表間關聯、離線操作 | 記憶體消耗高、操作較複雜、不適合單一表簡單操作 |
現代的開發系統則不是使用弱型別,而是先定義好資料物件,在讀取後將資料綁到List<物件>
當中,這種方式稱為強型別作法,好處是程式比較容易在編譯時發現錯誤,而且可以直接操作List物件做後續資料處哩
這邊我保留DataTable的作法,其他的部分刪除,程式碼如下
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace PartyRegister.Admin.Member
{
public partial class Manage : System.Web.UI.Page
{
/// <summary>
/// 連線字串
/// </summary>
private readonly string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
//判斷頁面是第一次載入時才更新
if(!IsPostBack)
{
BindData();
}
}
/// <summary>
/// GridView 讀取資料表
/// </summary>
private void BindData()
{
//讀取資料庫指令
string sql = "SELECT * FROM Member";
// 取得資料
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql,conn))
{
// 使用 DataTable讀取資料
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
gvList.DataSource = dt;
gvList.DataBind();
}
}
}
}
}
調整Manage.aspx 的GridView顯示欄位
如果出來的列表資料很少,就可以直接在列表上顯示,不過這邊我們要學怎麼在列表只顯示特定資料
調整列表顯示欄位
列表欄位:
- ID(主鍵-不顯示)
- 姓名
- 性別
- 報名場次
- 報名時間 (顯示yyyy/MM/dd hh:mm)
確定好列表欄位後,接下來我們要做的就是先改SQL
這邊我會直接開SSMS,然後對Member資料表選讀取前1000筆資料表,再將需要的欄位貼進來
//讀取資料庫指令
string sql = @"SELECT [ID],[Name],[Gender],[EventID],[CreateTime] FROM Member";
調整後的列表確實資訊變少了,不過畫面還是醜醜的,接下來我們要做幾件事
- 美化表格 套Bootstrap的CSS ,
table table-striped
,在GridView加上CssClass="table table-striped"
- 把欄位的英文名稱改成中文
- 加上編輯(藍字) 刪除(紅字)按鈕
- 性別轉換成 男(藍色) 女 (紅色)
- 報名時間改為顯示格式為
yyyy/MM/dd hh:mm
年/月/日 時:分
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin/Admin.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="PartyRegister.Admin.Member.Manage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>學員管理</h1>
<asp:GridView runat="server" ID="gvList" CssClass="table table-striped" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="操作">
<ItemTemplate>
<!-- 編輯按鈕 -->
<asp:LinkButton ID="btnEdit" runat="server" CommandName="Edit" Text="編輯" CssClass="text-primary"></asp:LinkButton>
|
<!-- 刪除按鈕,加入確認刪除提示 -->
<asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete" Text="刪除" CssClass="text-danger"
OnClientClick="return confirm('是否確定刪除?');"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name"></asp:BoundField>
<asp:TemplateField HeaderText="性別" SortExpression="Gender">
<ItemTemplate>
<asp:Label ID="lblGender" runat="server"
Text='<%# Eval("Gender").ToString() == "1" ? "男" : "女" %>'
ForeColor='<%# Eval("Gender").ToString() == "1" ? System.Drawing.Color.Blue : System.Drawing.Color.Pink %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EventID" HeaderText="場次" SortExpression="EventID"></asp:BoundField>
<asp:BoundField DataField="CreateTime" HeaderText="報名時間" SortExpression="CreateTime"
DataFormatString="{0:yyyy/MM/dd hh:mm}" />
</Columns>
</asp:GridView>
這邊詳細的說一下:
- GridView預設會依據欄位自動產生列表,我們將這個功能關閉,加上屬性
AutoGenerateColumns="false"
- 加上
<Columns></Columns>
來自訂要顯示的欄位 - 單純顯示資料使用
BoundField
就好,寫法是<asp:BoundField DataField="欄位名稱(資料庫)" HeaderText="欄位名稱(顯示在頁面上)" SortExpression="排序用欄位名稱(資料庫)"></asp:BoundField>
- 轉換日期時間顯示格式在
BoundField
加上DataFormatString="{0:yyyy/MM/dd hh:mm}"
- 性別跟編輯欄位要使用
TemplateField
功能,這個功能是在裡面塞入對應的樣板
偷吃步的作法(問AI)
其實可以先把欄位用BoundField
跟CommandField
列出來就好,然後請ChatGpt幫你做好上面的事情,一般來說我這樣寫剩下的靠AI就能準確地幫我完成大部分的工作
提問如下
<!-- 需求: 把編輯跟刪除合併為一欄,性別=1 顯示男生(藍色) 性別=2顯示為女生(紅色), 報名時間顯示為yyyy/MM/dd -->
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin/Admin.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="PartyRegister.Admin.Member.Manage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>學員管理</h1>
<asp:GridView runat="server" ID="gvList" CssClass="table table-striped" AutoGenerateColumns="false">
<Columns>
<asp:CommandField ShowSelectButton="true" SelectText="編輯" />
<asp:CommandField ShowSelectButton="true" SelectText="刪除" />
<asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name"></asp:BoundField>
<asp:BoundField DataField="Gender" HeaderText="性別" SortExpression="Gender"></asp:BoundField>
<asp:BoundField DataField="EventID" HeaderText="場次" SortExpression="EventID"></asp:BoundField>
<asp:BoundField DataField="CreateTime" HeaderText="報名時間" SortExpression="CreateTime"></asp:BoundField>
</Columns>
</asp:GridView>
</asp:Content>
AI產出的程式碼還是要自己看過,然後微調成需要的
加入分頁(單靠GridView的AutoPage)
GridView也能自動幫你處理好分頁,作法如下
Manage.aspx
的gvList加入屬性AllowPaging="true" OnPageIndexChanging="gvList_PageIndexChanging"
,告訴伺服器這個要做分頁Manage.aspx.cs
加入gvList_PageIndexChanging
事件處理,分頁處理上對於小資料做法還蠻固定的
注意,這個寫法其實還是把全部資料都讀進來,然後靠
GirdView
進行分頁,如果你的資料小於萬筆應該還可以,但如果資料是數十萬筆以上就不適合了,資料量大的時候就需要進行優化,詳見後續章節。
完成後的樣子(我有先補了資料 讓資料看起來比較像)
Manage.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin/Admin.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="PartyRegister.Admin.Member.Manage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>學員管理</h1>
<asp:GridView runat="server" ID="gvList" CssClass="table table-striped" AutoGenerateColumns="false"
AllowPaging="true" OnPageIndexChanging="gvList_PageIndexChanging">
<Columns>
<asp:TemplateField HeaderText="操作">
<ItemTemplate>
<!-- 編輯按鈕 -->
<asp:LinkButton ID="btnEdit" runat="server" CommandName="Edit" Text="編輯" CssClass="text-primary"></asp:LinkButton>
|
<!-- 刪除按鈕,加入確認刪除提示 -->
<asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete" Text="刪除" CssClass="text-danger"
OnClientClick="return confirm('是否確定刪除?');"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name"></asp:BoundField>
<asp:TemplateField HeaderText="性別" SortExpression="Gender">
<ItemTemplate>
<asp:Label ID="lblGender" runat="server"
Text='<%# Eval("Gender").ToString() == "1" ? "男" : "女" %>'
ForeColor='<%# Eval("Gender").ToString() == "1" ? System.Drawing.Color.Blue : System.Drawing.Color.Pink %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EventID" HeaderText="場次" SortExpression="EventID"></asp:BoundField>
<asp:BoundField DataField="CreateTime" HeaderText="報名時間" SortExpression="CreateTime"
DataFormatString="{0:yyyy/MM/dd hh:mm}" />
</Columns>
</asp:GridView>
</asp:Content>
Manage.aspx.cs
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace PartyRegister.Admin.Member
{
public partial class Manage : System.Web.UI.Page
{
/// <summary>
/// 連線字串
/// </summary>
private readonly string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
//判斷頁面是第一次載入時才更新
if(!IsPostBack)
{
BindData();
}
}
/// <summary>
/// GridView 讀取資料表
/// </summary>
private void BindData()
{
//讀取資料庫指令
string sql = @"SELECT [ID],[Name],[Gender],[EventID],[CreateTime] FROM Member";
// 取得資料
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql,conn))
{
// 使用 DataTable讀取資料
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
gvList.DataSource = dt;
gvList.DataBind();
}
}
}
/// <summary>
/// GridView 分頁
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void gvList_PageIndexChanging(object sender, System.Web.UI.WebControls.GridViewPageEventArgs e)
{
var page = e.NewPageIndex;
gvList.PageIndex = page;
BindData();
}
}
}
GridView 加入每頁筆數選擇功能
AI指令: 原始碼+幫我加上一個選擇每頁筆數的下拉選單,選項有10 30 50 100 200筆
Manage.aspx
前端加入每頁頁數的下拉選單
<!-- 每頁筆數下拉選單 -->
<asp:DropDownList ID="ddlPageSize" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddlPageSize_SelectedIndexChanged">
<asp:ListItem Text="10" Value="10" Selected="True" />
<asp:ListItem Text="30" Value="30" />
<asp:ListItem Text="50" Value="50" />
<asp:ListItem Text="100" Value="100" />
<asp:ListItem Text="200" Value="200" />
</asp:DropDownList>
Manage.aspx.cs
後端加入ddlPageSize_SelectedIndexChanged
這個事件
/// <summary>
/// 下拉選單變更事件,更新 GridView 每頁筆數
/// </summary>
protected void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e)
{
//取得每頁筆數設定
gvList.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
// 重設頁碼,顯示第一頁
gvList.PageIndex = 0;
//重新綁定資料
BindData();
}
GridView前加入總筆數顯示
AI指令: 原始碼+幫我加上總筆數顯示功能
做法:
Manage.aspx
的GridView
前加入總筆數的Label
Manage.aspx.cs
的DataBind()
加入總筆數查詢的程式碼
Manage.aspx
端,這邊加在每頁筆數下拉選單的前後,如下
每頁 <asp:DropDownList ID="ddlPageSize" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddlPageSize_SelectedIndexChanged">
<asp:ListItem Text="10" Value="10" Selected="True" />
<asp:ListItem Text="30" Value="30" />
<asp:ListItem Text="50" Value="50" />
<asp:ListItem Text="100" Value="100" />
<asp:ListItem Text="200" Value="200" />
</asp:DropDownList> 筆,查詢結果共<asp:Label ID="lbTotalCount" runat="server"></asp:Label>筆資料
Manage.aspx.cs
端,改寫BindData
/// <summary>
/// GridView 讀取資料表
/// </summary>
private void BindData()
{
//讀取資料庫指令
string sql = @"SELECT [ID],[Name],[Gender],[EventID],[CreateTime] FROM Member";
//string sql = @"SELECT * FROM Member";
// 取得資料
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
//讀取資料列表
using (var cmd = new SqlCommand(sql,conn))
{
// 使用 DataTable讀取資料
DataTable dt = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
gvList.DataSource = dt;
gvList.DataBind();
}
//取得總共幾筆資料
string sqlCount = @"SELECT COUNT(1) FROM Member";
using (var cmd = new SqlCommand(sqlCount, conn))
{
lbTotalCount.Text = cmd.ExecuteScalar().ToString();
}
}
}
優化GridView分頁
AI指令: 幫我改為透過SQL SERVER
進行查詢分頁,使用FETCH
跟OFFSET
要做SQL分頁最常見是透過FETCH NEXT
跟OFFSET
這兩個指令組合出來的分頁,寫法是
SELECT 列表中的欄位
FROM 資料表
ORDER BY 排序欄位 ASC
OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY ;
OFFSET
是要跳過幾筆ROWS FETCH NEXT @PageSize ROWS ONLY
是要抓接下來的幾筆@Offset
= 頁碼 * 每頁筆數@PageSize
= 每頁筆數
在來一改成自行分頁後GridView那邊就要啟用自訂分頁的功能 AllowCustomPaging="true"
Manage.aspx.cs
那邊的DataBind()
要大幅改寫
改好的程式碼如下
Manage.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Admin/Admin.Master" AutoEventWireup="true" CodeBehind="Manage.aspx.cs" Inherits="PartyRegister.Admin.Member.Manage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>學員管理</h1>
<!-- 每頁筆數下拉選單 -->
每頁 <asp:DropDownList ID="ddlPageSize" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddlPageSize_SelectedIndexChanged">
<asp:ListItem Text="10" Value="10" Selected="True" />
<asp:ListItem Text="30" Value="30" />
<asp:ListItem Text="50" Value="50" />
<asp:ListItem Text="100" Value="100" />
<asp:ListItem Text="200" Value="200" />
</asp:DropDownList> 筆,查詢結果共<asp:Label ID="lbTotalCount" runat="server"></asp:Label>筆資料
<asp:GridView runat="server" ID="gvList" CssClass="table table-striped" AutoGenerateColumns="false" AllowCustomPaging="true"
AllowPaging="true" OnPageIndexChanging="gvList_PageIndexChanging">
<Columns>
<asp:TemplateField HeaderText="操作">
<ItemTemplate>
<!-- 編輯按鈕 -->
<asp:LinkButton ID="btnEdit" runat="server" CommandName="Edit" Text="編輯" CssClass="text-primary"></asp:LinkButton>
|
<!-- 刪除按鈕,加入確認刪除提示 -->
<asp:LinkButton ID="btnDelete" runat="server" CommandName="Delete" Text="刪除" CssClass="text-danger"
OnClientClick="return confirm('是否確定刪除?');"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name"></asp:BoundField>
<asp:TemplateField HeaderText="性別" SortExpression="Gender">
<ItemTemplate>
<asp:Label ID="lblGender" runat="server"
Text='<%# Eval("Gender").ToString() == "1" ? "男" : "女" %>'
ForeColor='<%# Eval("Gender").ToString() == "1" ? System.Drawing.Color.Blue : System.Drawing.Color.Pink %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EventID" HeaderText="場次" SortExpression="EventID"></asp:BoundField>
<asp:BoundField DataField="CreateTime" HeaderText="報名時間" SortExpression="CreateTime"
DataFormatString="{0:yyyy/MM/dd hh:mm}" />
</Columns>
</asp:GridView>
</asp:Content>
Manage.aspx.cs
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace PartyRegister.Admin.Member
{
public partial class Manage : System.Web.UI.Page
{
/// <summary>
/// 連線字串
/// </summary>
private readonly string connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
//判斷頁面是第一次載入時才更新
if(!IsPostBack)
{
// 初始時依下拉選單預設值設定每頁筆數
gvList.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
BindData();
}
}
/// <summary>
/// GridView 讀取資料表
/// </summary>
private void BindData()
{
//查詢結果總筆數
int totalCount = 0;
//分頁大小
int pageSize = gvList.PageSize;
//第幾頁
int pageIndex = gvList.PageIndex;
//計算要跳過幾筆
int offset = pageIndex * pageSize;
// 讀取資料庫指令
string sql = @"
SELECT [ID], [Name], [Gender], [EventID], [CreateTime]
FROM Member
ORDER BY [ID] ASC
OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY ;";
//string sql = @"SELECT * FROM Member";
// 取得資料
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
DataTable dt = new DataTable();
using (var cmd = new SqlCommand(sql,conn))
{
// 開始列
cmd.Parameters.AddWithValue("@Offset", offset);
cmd.Parameters.AddWithValue("@PageSize", pageSize);
// 使用 DataTable讀取資料
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
//取得總共幾筆資料
string sqlCount = @"SELECT COUNT(1) FROM Member";
using (var cmd = new SqlCommand(sqlCount, conn))
{
totalCount = Convert.ToInt32(cmd.ExecuteScalar());
lbTotalCount.Text = totalCount.ToString();
}
// 設定 VirtualItemCount 使 GridView 分頁控制項能顯示正確總頁數
gvList.VirtualItemCount = totalCount;
gvList.DataSource = dt;
gvList.DataBind();
}
}
/// <summary>
/// GridView 分頁
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void gvList_PageIndexChanging(object sender, System.Web.UI.WebControls.GridViewPageEventArgs e)
{
//取得新的所在頁碼
var page = e.NewPageIndex;
//設定頁數
gvList.PageIndex = page;
//重新綁定資料
BindData();
}
/// <summary>
/// 下拉選單變更事件,更新 GridView 每頁筆數
/// </summary>
protected void ddlPageSize_SelectedIndexChanged(object sender, EventArgs e)
{
//取得每頁筆數設定
gvList.PageSize = Convert.ToInt32(ddlPageSize.SelectedValue);
// 重設頁碼,顯示第一頁
gvList.PageIndex = 0;
//重新綁定資料
BindData();
}
}
}
雖然目前這個範例的資料很少,不過我們還是要學習正規的作法。
GridView 加入刪除功能
前面已經把GridView
主要功能先做好了,接下來我們先從簡單的「刪除」開始做,接著再做編輯功能。
GridView加入
- 加入當按下編輯跟刪除要觸發的事件
OnRowCommand
- 編輯跟刪除都要加入
CommandName
與CommandArgument
這兩個是觸發OnRowCommand
時候會跟著傳入的參數 - 這邊的
CommandName
傳入參數不可以用Edit
跟Delete
,這會導致觸發另一個事件。
<asp:GridView runat="server" ID="gvList" CssClass="table table-striped" AutoGenerateColumns="false" AllowCustomPaging="true"
AllowPaging="true" OnPageIndexChanging="gvList_PageIndexChanging" OnRowCommand="gvList_RowCommand">
<Columns>
<asp:TemplateField HeaderText="操作">
<ItemTemplate>
<!-- 編輯按鈕 -->
<asp:LinkButton ID="btnEdit" runat="server" CommandName="EditData" Text="編輯" CommandArgument='<%# Eval("ID") %>' CssClass="text-primary"></asp:LinkButton>
|
<!-- 刪除按鈕,加入確認刪除提示 -->
<asp:LinkButton ID="btnDelete" runat="server" CommandName="DeleteData" Text="刪除" CommandArgument='<%# Eval("ID") %>' CssClass="text-danger"
OnClientClick="return confirm('是否確定刪除?');"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="姓名" SortExpression="Name"></asp:BoundField>
<asp:TemplateField HeaderText="性別" SortExpression="Gender">
<ItemTemplate>
<asp:Label ID="lblGender" runat="server"
Text='<%# Eval("Gender").ToString() == "1" ? "男" : "女" %>'
ForeColor='<%# Eval("Gender").ToString() == "1" ? System.Drawing.Color.Blue : System.Drawing.Color.Pink %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EventID" HeaderText="場次" SortExpression="EventID"></asp:BoundField>
<asp:BoundField DataField="CreateTime" HeaderText="報名時間" SortExpression="CreateTime"
DataFormatString="{0:yyyy/MM/dd hh:mm}" />
</Columns>
</asp:GridView>
後端Manage.aspx.cs
的部分則是加入gvList_RowCommand
這個事件
/// <summary>
/// GridView 按下編輯或刪除按鈕
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void gvList_RowCommand(object sender, GridViewCommandEventArgs e)
{
//注意 這邊的CommandName不能只取名為Edit跟Delete 原因是會造成觸發另一種RowEdit事件
//這邊的CommandName對應前端GridView按鈕的CommandName=""屬性
if (e.CommandName == "EditData")
{
//這邊ID如果取不到就是前端GridView按鈕少寫 CommandArgument='<%# Eval("ID") %>'
string id = e.CommandArgument.ToString();
//TODO 執行編輯邏輯
}
else if (e.CommandName == "DeleteData")
{
string id = e.CommandArgument.ToString();
//TODO 執行刪除邏輯
}
}
接下來可以先試看看編輯跟刪除是否能正確觸發並取得ID
如圖
這樣寫一段,測試一段對於開發上很重要的
接著刪除選定資料邏輯如下,這是直接執行SQL語法,不讀取返回資料,DELETE跟UPDATE都是這樣寫。刪除後記得要重新載入列表。
//刪除選定資料
string id = e.CommandArgument.ToString();
const string sql = "DELETE Member WHERE ID = @id ";
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
//加入參數
cmd.Parameters.AddWithValue("@id", id);
//不讀取返回資料
cmd.ExecuteNonQuery();
}
}
//刪除後重新載入列表
BindData();
測試刪除功能,觀察刪除後列表是否有更新,刪除的項目是否已經從列表消失。
這邊介紹的作法叫做「硬刪除」,意思是直接在資料庫刪除資料,另一種作法「軟刪除」則是在資料庫欄位欄位上設定一個刪除旗標,刪除資料時僅更新該旗標。
0 Comments