ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย Code Behind

เช่นเคยครับ จากบล็อก ขยับแถว (row) ขึ้น/ลง ใน ASP.NET Gridview ด้วย jQuery เป็นการเพิ่มฟีเจอร์ให้กับ ASP.NET Gridview ด้วยการประยุกต์ใช้ jQuery บทความต่อมา ก็จะเป็นการเพิ่มฟีเจอร์เดียวกัน แต่จะเป็นการพัฒนาด้วยโค้ดฝั่ง code behind

เนื่องจากการทำงานฝั่ง code behind จะไม่สามารถเคลื่อนย้ายเร็คคอร์ดของ gridview ได้โดยตรง ดังนั้นเราจะทำทางอ้อม ด้วยการใช้ฟิลด์ในตารางฟิลด์หนึ่งมาเป็นข้อมูลสำหรับเรียงใน Gridview เมื่อต้องการย้ายเร็คคอร์ด เราก็จะเปลี่ยนตัวเลขในฟิลด์นี้ แล้วทำการเรียงข้อมูลใหม่ และแสดงผลข้อมูลใน Gridview อีกครั้ง ไปดูขั้นตอนต่างๆ กันเลยครับ

1. ในส่วนของโค้ด HTML จะมีการปรับปรุงเพิ่มเล็กน้อยเฉพาะในส่วนของปุ่ม UP/DOWN ซึ่งเราจะเปลี่ยนไปใช้ปุ่มที่เป็นคอนโทรลของ ASP.NET เพื่อให้สามารถเขียนโปรแกรมควบคุมจากฝั่ง code behind ได้

<asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False" OnRowCommand="gvBib_RowCommand" >
    <Columns>
        <asp:BoundField DataField="BIB_NO" HeaderText="Bib#" />
        <asp:BoundField DataField="TITLE" HeaderText="Title" />
        <asp:BoundField DataField="AUTHOR" HeaderText="Author" />
        <asp:BoundField DataField="CALL_NO" HeaderText="CallNo" />
        <asp:BoundField DataField="ISBN" HeaderText="ISBN" />
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Button ID="btnUp" runat="server" Text="UP" CommandName="up" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
                <asp:Button ID="btnDown" runat="server" Text="DOWN" CommandName="down" CommandArgument="<%# ((GridViewRow) Container).RowIndex %>"></asp:Button>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

โดย

  • CommndName ใช้สำหรับตรวจสอบว่าเป็นการเลือก up หรือ down
  • CommandArgument ใช้สำหรับระบุแถวที่คลิกเลือก

2. ในส่วนของโค้ดที่ใช้สร้างข้อมูลเพื่อแสดงใน Gridview เราจะเพิ่มฟิลด์ขึ้นมาอีก 1 ฟิลด์ เพื่อใช้กำหนดลำดับการแสดงผล จากตัวอย่างโค้ด ก็คือฟิลด์ SEQ

DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[6] { new DataColumn("BIB_NO"), 
                                        new DataColumn("TITLE"), 
                                        new DataColumn("AUTHOR"),
                                        new DataColumn("CALL_NO"),
                                        new DataColumn("ISBN"),
                                        new DataColumn("SEQ")});
dt.Rows.Add("001", "1 ทศวรรษ ดัชนีสุขภาพคนไทย", "สำนักงานคณะกรรมการสุขภาพแห่งชาติ (สช.)", "WA13 ห159 2556", "9786160822258", 1);
dt.Rows.Add("002", "ความลับในร่างกายมนุษย์ที่เราไม่เคยรู้", "ฟรานซิส, เกวิน", "QS4 ฟ133a 2560", "9786168022887", 2);
dt.Rows.Add("003", "The best ICU", "ดุสิต สถาวร", "WX218 B561 2560", "9786168122020", 3);
dt.Rows.Add("004", "COVID-19 โรคระบาดแห่งศตวรรษ", "นำชัย ชีววิวรรธน์", "QW168.5.C8 น515c 2563", "9789740217060", 4);
dt.Rows.Add("005", "Good health & smart life ในวัย 40+", "ไวต์, จอห์น", "WT104 ว967g 2560", "9786160827237", 5);
gvBib.DataSource = dt;
gvBib.DataBind();

//เก็บข้อมูล
ViewState["dtBook"] = dt;

3. เพิ่มโค้ดในส่วนของ gvBib_RowCommand ซึ่งเป็น event ที่จะเกิดเมื่อมีการคลิกปุ่ม UP หรือ DOWN

protected void gvBib_RowCommand(object sender, GridViewCommandEventArgs e)
{
	DataTable dt = (DataTable)ViewState["dtBook"];

        //เก็บแถวที่คลิกเลือก
	int curIdx = Convert.ToInt32(e.CommandArgument);

	if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
	{
		//กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
		dt.Rows[curIdx - 1]["SEQ"] = curIdx;
		dt.Rows[curIdx]["SEQ"] = curIdx - 1;
	}
	else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
	{
		//กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
		dt.Rows[curIdx + 1]["SEQ"] = curIdx;
		dt.Rows[curIdx]["SEQ"] = curIdx + 1;
	}
	dt.AcceptChanges();

	//กำหนดให้ข้อมูลเรียงตามฟิลด์ SEQ
	dt.DefaultView.Sort = "SEQ";

	//เซ็ตข้อมูลที่มีการเรียงลำกับแล้วกลับไปให้ DataTable
	dt = dt.DefaultView.ToTable();

	//กำหนดข้อมูลที่เรียงลำดับใหม่แล้วให้กับ Gridview และแสดผล
	gvBib.DataSource = dt;
	gvBib.DataBind();

	//เก็บข้อมูลกลับเข้า ViewState
	ViewState["dtBook"] = dt;
}

เมื่อทดลองรัน จะปรากฏผลลัพธ์ดังรูปด้านล่าง

เมื่อทดลองคลิกปุ่ม UP หรือ DOWN ระบบก็สามารถย้ายแถวที่ต้องการไปยังตำแหน่งที่ก่อนหน้าหรือถัดไปได้อย่างถูกต้อง ยกเว้นการคลิก UP ที่แถวแรก และ DOWN ที่แถวสุดท้าย จะเกิด Error ดังภาพ

และ
ซึ่งเกิดจากการเลื่อนไปยังตำแหน่งที่ไม่มีในข้อมูล จึงจะต้องปรับแก้โค้ดอีกเล็กน้อยดังนี้
//เก็บแถวที่คลิกเลือก
int curIdx = Convert.ToInt32(e.CommandArgument);

if(e.CommandName == "up")   //ถ้ากดปุ่ม UP
{
    //ตรวจสอบว่าไม่ใช่แถวแรกหรือไม่
    if (curIdx != 0)
    {
        //กำหนดลำดับใหม่ให้กับแถวก่อนหน้ากับแถวปัจจุบันให้สลับกัน
        dt.Rows[curIdx - 1]["SEQ"] = curIdx;
        dt.Rows[curIdx]["SEQ"] = curIdx - 1;
    }
}
else if (e.CommandName == "down")   //ถ้ากดปุ่ม DOWN
{
    //ตรวจสอบว่าไม่ใช่แถวสุดท้ายหรือไม่
    if (curIdx != dt.Rows.Count - 1)
    {
        //กำหนดลำดับใหม่ให้กับแถวถัดไปกับแถวปัจจุบันให้สลับกัน
        dt.Rows[curIdx + 1]["SEQ"] = curIdx;
        dt.Rows[curIdx]["SEQ"] = curIdx + 1;
    }
}

โดยเราจะต้องตรวจสอบเพิ่มเติมก่อนว่า เมื่อคลิกปุ่ม UP จะต้องไม่ใช่แถวแรก และคลิกปุ่ม DOWN จะต้องไม่ใช่แถวสุดท้าย เมื่อทดสอบรันอีกครั้ง ก็พบว่าสามารถทำงานได้ปกติ เมื่อคลิกปุ่ม UP ที่แถวแรก หรือปุ่ม DOWN ที่แถวสุดท้าย ก็จะไม่เกิด Error

ผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้จะมีประโยชน์ไม่มากก็น้อย ที่ผู้อ่านน่าจะสามารถนำไปประยุกต์ใช้ในงานของตัวเอง

จนกว่าจะพบกันใหม่ สวัสดีครับ


แหล่งข้อมูลอ้างอิง