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

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

โดยมีขั้นตอนดังต่อไปนี้

1. เพิ่มโค้ด HTML สำหรับแสดงผลข้อมูล Gridview

<asp:ScriptManager runat="server"></asp:ScriptManager>

<asp:GridView ID="gvBib" runat="server" AutoGenerateColumns="False">
    <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:UpdatePanel runat="server">
                    <ContentTemplate>
                        <button class="up">UP</button>
                        <button class="down">DOWN</button>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

จะสังเกตว่าจะมีฟิลด์ที่เป็น ItemTemplate สำหรับแสดงผลปุ่ม UP และปุ่ม DOWN สำหรับใช้ในการเลื่อน row นั้นๆ ขึ้นหรือลง

และเหตุผลที่จะต้องมี UpdatePanel ครอบปุ่มไว้ เพราะทุกครั้งที่มีการกด จะเกิดการ Postback ทำให้ข้อมูลจะถูก Bind ซ้ำ การเรียงลำดับก็จะกลับคืนไปเหมือนเดิม จึงจำเป็นต้องทำ Partial Load เพื่อป้องกันการ Bind ข้อมูลซ้ำ

2. เพิ่มโค้ดใน event Page_Load ในหน้า code behind เพื่อจำลองข้อมูลที่จะใช้แสดงใน GridView

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

เนื่องจากโค้ดตัวอย่างมีการใช้งาน class DataTable และ DataColumn ซึ่งอยู่ใน namespace System.Data เพราะฉะนั้นจะต้อง Import namespace นี้ด้วย

using System.Data;

3. เพิ่มโค้ด jQuery สำหรับควบคุมการทำงานปุ่ม UP/DOWN โดยหลักการทำงานคือ เมื่อคลิกปุ่ม UP หรือ DOWN แถวที่เลือก จะถูกขยับหรือลง 1 เรคคอร์ด

//เมื่อคลิกปุ่ม UP
$(document).on("click", ".up", function () {

    //เก็บเร็คคอร์ดที่ถูกคลิกเอาไว้
    var curRow = $(this).closest('tr');


    //ย้ายเร็คคอร์ดปัจจุบัน ไปอยู่ในตำแหน่งก่อนหน้า เร็คคอร์ดที่อยู่ก่อนหน้า
    curRow.insertBefore(curRow.prev());

});

//เมื่อคลิกปุ่ม DOWN
$(document).on("click", ".down", function () {
    var curRow = $(this).closest('tr');
    curRow.insertAfter(curRow.next());
});

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

เมื่อทดลองกดปุ่ม UP ในช่อง Bib#005 เรคคอร์ดนั้นก็จะขยับขึ้นไปอยู่บน Bib#004 ดังรูป
แต่ถ้าทดลองกดปุ่ม UP ในเรคคอร์ด Bib#001 เรคคอร์ดนี้จะถูกเลื่อนขึ้นไปอยู่เหนือเรคคอร์ดที่เป็น Header ของตารางซึ่งไม่ถูกต้อง
4. เราจะต้องแก้ไขโค้ด jQuery เพิ่มเติม โดยแก้ไขเฉพาะกรณีคลิกปุ่ม UP เพื่อตรวจสอบก่อนว่า เรคคอร์ดที่คลิกเป็นเรคคอร์ดบนสุด (ยกเว้น header) หรือยัง
//เมื่อคลิกปุ่ม UP
$(document).on("click", ".up", function () {

    //เก็บเร็คคอร์ดที่ถูกคลิกเอาไว้
    var curRow = $(this).closest("tr");

    //เก็บเร็คคอร์ดแรกสุดของตารางเอาไว้ ซึ่งก็คือเรคคอร์ดหัวตาราง 
    //ที่เราจะไม่อนุญาตให้เอาเรคคอร์ดอื่นมาแทรก
    var firstRow = $("[id*=gvBib] tr:first");

    //ตรวจสอบว่าเร็คอคอร์ดก่อนหน้าของเร็คคอร์ดที่เรากดปุ่ม คือเร็คคอร็ดที่เป็นหัวตารางหรือไม่
    //ถ้าไม่ใช่ก็จะทำการย้ายเร็คคอร์ด
    if (curRow.prev().html() != firstRow.html() ) {

        //ย้ายเร็คคอร์ดปัจจุบัน ไปอยู่ในตำแหน่งก่อนหน้า เร็คคอร์ดที่อยู่ก่อนหน้า
        curRow.insertBefore(curRow.prev());
    }
});

เมื่อทดสอบอีกครั้ง ก็จะพบว่า ไม่สามารถกด UP เรคคอร์ดที่อยู่ใต้ Header ได้อีกแล้ว

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


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

  • https://stackoverflow.com/questions/16524497/jquery-to-move-row-up-and-down
  • https://stackoverflow.com/questions/36243730/jquery-to-compare-rows-in-two-tables