Bagikan melalui


Membuat Antarmuka Pengguna Pengurutan yang Dikustomisasi (VB)

oleh Scott Mitchell

Unduh PDF

Saat menampilkan daftar panjang data yang diurutkan, akan sangat membantu untuk mengelompokkan data terkait dengan memperkenalkan baris pemisah. Dalam tutorial ini kita akan melihat cara membuat antarmuka pengguna pengurutan seperti itu.

Pendahuluan

Saat menampilkan daftar panjang data yang diurutkan di mana hanya ada beberapa nilai berbeda di kolom yang diurutkan, pengguna akhir mungkin merasa sulit untuk membedakan di mana, tepatnya, batas perbedaan terjadi. Misalnya, ada 81 produk dalam database, tetapi hanya sembilan pilihan kategori yang berbeda (delapan kategori unik ditambah NULL opsi). Pertimbangkan kasus pengguna yang tertarik untuk memeriksa produk yang termasuk dalam kategori Makanan Laut. Dari halaman yang mencantumkan semua produk dalam satu GridView, pengguna dapat memutuskan best bet-nya adalah mengurutkan hasil berdasarkan kategori, yang akan mengelompokkan semua produk Seafood bersama-sama. Setelah mengurutkan berdasarkan kategori, pengguna kemudian perlu menelusuri daftar, mencari di mana produk yang dikelompokkan dalam kategori Makanan Laut dimulai dan diakhiri. Karena hasilnya diurutkan menurut abjad berdasarkan nama kategori, menemukan produk Makanan Laut tidaklah sulit, tetapi tetap memerlukan menelusuri daftar item di dalam grid.

Untuk membantu menyoroti batas antara grup yang diurutkan, banyak situs web menggunakan antarmuka pengguna yang menambahkan pemisah antara grup tersebut. Pemisah seperti yang ditunjukkan pada Gambar 1 memungkinkan pengguna untuk lebih cepat menemukan grup tertentu dan mengidentifikasi batas-batasnya, serta memastikan grup berbeda apa yang ada dalam data.

Setiap Grup Kategori Diidentifikasi Dengan Jelas

Gambar 1: Setiap Grup Kategori Diidentifikasi Dengan Jelas (Klik untuk melihat gambar ukuran penuh)

Dalam tutorial ini kita akan melihat cara membuat antarmuka pengguna pengurutan seperti itu.

Langkah 1: Membuat GridView Standar yang Dapat Diurutkan

Sebelum kita menjelajahi cara menambah GridView untuk menyediakan antarmuka pengurutan yang ditingkatkan, mari kita buat GridView standar dan dapat diurutkan terlebih dahulu yang mencantumkan produk. Mulailah dengan membuka CustomSortingUI.aspx halaman di PagingAndSorting folder. Tambahkan GridView ke halaman, atur propertinya ID ke ProductList, dan ikat ke ObjectDataSource baru. Konfigurasikan ObjectDataSource untuk menggunakan ProductsBLL metode kelas s GetProducts() untuk memilih rekaman.

Selanjutnya, konfigurasikan GridView sehingga hanya berisi ProductName, CategoryName, SupplierName, dan UnitPrice BoundFields serta CheckBoxField Discontinued. Terakhir, konfigurasikan GridView untuk mendukung pengurutan dengan mencentang kotak centang Aktifkan Pengurutan di tag pintar GridView (atau dengan mengatur propertinya AllowSorting ke true). Setelah membuat penambahan ini ke CustomSortingUI.aspx halaman, markup deklaratif akan terlihat mirip dengan yang berikut ini:

<asp:GridView ID="ProductList" runat="server" AllowSorting="True"
    AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier"
            ReadOnly="True" SortExpression="SupplierName" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:C}"
            HeaderText="Price" HtmlEncode="False" SortExpression="UnitPrice" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
    TypeName="ProductsBLL"></asp:ObjectDataSource>

Luangkan waktu sejenak untuk melihat kemajuan kami sejauh ini di browser. Gambar 2 memperlihatkan GridView yang dapat diurutkan saat datanya diurutkan menurut kategori dalam urutan alfabet.

Data GridView yang Dapat Diurutkan diurutkan menurut Kategori

Gambar 2: Data GridView yang Dapat Diurutkan Diurutkan menurut Kategori (Klik untuk melihat gambar ukuran penuh)

Langkah 2: Menjelajahi Teknik untuk Menambahkan Baris Pemisah

Dengan GridView generik yang sudah selesai diatur dan dapat diurutkan, langkah berikutnya adalah menambahkan baris pemisah di GridView sebelum setiap kelompok unik yang diurutkan. Namun, bagaimana baris-baris tersebut dapat ditambahkan ke dalam GridView? Pada dasarnya, kita perlu melakukan iterasi melalui baris GridView s, menentukan di mana perbedaan terjadi antara nilai di kolom yang diurutkan, lalu menambahkan baris pemisah yang sesuai. Ketika memikirkan masalah ini, tampaknya wajar bahwa solusinya terletak di suatu tempat di penanganan aktivitas GridView RowDataBound . Seperti yang kita bahas dalam tutorial Pemformatan Kustom Berdasarkan Data , penanganan aktivitas ini biasanya digunakan saat menerapkan pemformatan tingkat baris berdasarkan data baris. Namun, penanganan RowDataBound aktivitas bukan solusi di sini, karena baris tidak dapat ditambahkan ke GridView secara terprogram dari penanganan aktivitas ini. Koleksi GridView Rows , pada kenyataannya, bersifat hanya dapat dibaca.

Untuk menambahkan baris tambahan ke GridView, kami memiliki tiga pilihan:

  • Tambahkan baris pemisah metadata ini ke data aktual yang terikat ke GridView
  • Setelah GridView terikat ke data, tambahkan instans tambahan TableRow ke koleksi kontrol GridView
  • Membuat kontrol server kustom yang memperluas kontrol GridView dan mengambil alih metode yang bertanggung jawab untuk membangun struktur GridView

Membuat kontrol server kustom akan menjadi pendekatan terbaik jika fungsionalitas ini diperlukan di banyak halaman web atau di beberapa situs web. Namun, itu akan memerlukan sedikit kode dan eksplorasi menyeluruh ke kedalaman pekerjaan internal GridView. Oleh karena itu, kami tidak akan mempertimbangkan opsi itu untuk tutorial ini.

Dua opsi lainnya menambahkan baris pemisah ke data sebenarnya yang terikat ke GridView dan memanipulasi koleksi kontrol GridView setelah data terikat - menangani masalah secara berbeda dan layak untuk dibahas.

Menambahkan Baris ke Terikat Data ke GridView

Saat GridView terikat ke sumber data, GridView membuat sebuah GridViewRow untuk setiap rekaman yang dikembalikan oleh sumber data. Oleh karena itu, kita dapat menyuntikkan baris pemisah yang diperlukan dengan menambahkan rekaman pemisah ke sumber data sebelum mengikatnya ke GridView. Gambar 3 menggambarkan konsep ini.

Satu Teknik Melibatkan Penambahan Baris Pemisah ke Sumber Data

Gambar 3: Satu Teknik Melibatkan Penambahan Baris Pemisah ke Sumber Data

Saya menggunakan istilah "rekaman pemisah" dalam tanda kutip karena tidak ada rekaman pemisah khusus; melainkan, kita harus entah bagaimana menandai bahwa rekaman tertentu dalam sumber data berfungsi sebagai pemisah daripada baris data biasa. Untuk contoh kami, kami mengikat instans ProductsDataTable ke GridView, yang terdiri dari ProductRows. Kami mungkin menandai rekaman sebagai baris pemisah dengan mengatur propertinya CategoryID ke -1 (karena nilai seperti itu tidak dapat ada secara normal).

Untuk menggunakan teknik ini, kita perlu melakukan langkah-langkah berikut:

  1. Mengambil data secara programatis untuk dihubungkan ke GridView ( ProductsDataTable instance)
  2. Mengurutkan data berdasarkan properti GridView SortExpression dan SortDirection
  3. Lakukan iterasi melalui ProductsRows di dalam ProductsDataTable, sambil mencari tempat letak perbedaan dalam kolom yang diurutkan.
  4. Di setiap batas grup, masukkan instans rekaman ProductsRow pemisah ke dalam DataTable, yang telah CategoryID diatur ke -1 (atau penunjukan apa pun yang diputuskan untuk menandai rekaman sebagai rekaman pemisah )
  5. Setelah menyuntikkan baris pemisah, secara terprogram mengikat data ke GridView

Selain lima langkah ini, kita juga perlu menyediakan penanganan aktivitas untuk acara GridView RowDataBound . Di sini, kami memeriksa masing-masing DataRow dan menentukan apakah itu baris pemisah, yang pengaturannya CategoryID adalah -1. Jika demikian, kita mungkin ingin menyesuaikan pemformatannya atau teks yang ditampilkan dalam sel.

Menggunakan teknik ini untuk menyuntikkan batas grup pengurutan memerlukan sedikit lebih banyak pekerjaan daripada yang diuraikan di atas, karena Anda juga perlu menyediakan pengendali acara untuk acara GridView Sorting dan melacak nilai SortExpression dan SortDirection.

Memanipulasi Koleksi Kontrol pada GridView Setelah Data Terikat

Daripada mengirimkan pesan data sebelum mengikatnya ke GridView, kita dapat menambahkan baris pemisah setelah data terikat ke GridView. Proses pengikatan data membangun hierarki kontrol GridView, yang pada kenyataannya hanyalah instans yang Table terdiri dari kumpulan baris, yang masing-masing terdiri dari kumpulan sel. Secara khusus, koleksi kontrol berisi objek Table di akar, GridViewRow (yang berasal dari kelas TableRow) untuk setiap rekaman yang terikat pada DataSource GridView, dan objek TableCell di setiap instance GridViewRow untuk setiap bidang data di DataSource.

Untuk menambahkan baris pemisah antara setiap grup pengurutan, kita dapat langsung memanipulasi hierarki kontrol ini setelah dibuat. Kami dapat yakin bahwa hierarki kontrol GridView telah dibuat untuk terakhir kalinya pada saat halaman dirender. Oleh karena itu, pendekatan ini mengambil alih Page metode kelas s Render , di mana hierarki kontrol akhir GridView diperbarui untuk menyertakan baris pemisah yang diperlukan. Gambar 4 mengilustrasikan proses ini.

Teknik Alternatif untuk Memanipulasi Hierarki Kontrol pada GridView

Gambar 4: Teknik Alternatif Memanipulasi Hierarki Kontrol GridView (Klik untuk melihat gambar ukuran penuh)

Untuk tutorial ini, kita akan menggunakan pendekatan terakhir ini untuk menyesuaikan pengalaman pengguna pengurutan.

Nota

Kode yang saya sajikan dalam tutorial ini didasarkan pada contoh yang disediakan dalam entri blog Teemu Keiski, Mencoba-coba dengan Pengelompokan Pengurutan GridView.

Langkah 3: Menambahkan Baris Pemisah ke Hierarki Kontrol GridView

Karena kami hanya ingin menambahkan baris pemisah ke hierarki kontrol GridView setelah hierarki kontrolnya dibuat dan dibuat untuk terakhir kalinya pada kunjungan halaman tersebut, kami ingin melakukan penambahan ini di akhir siklus hidup halaman, tetapi sebelum hierarki kontrol GridView yang sebenarnya telah dirender ke html. Titik terakhir yang memungkinkan kita untuk mencapai ini adalah acara kelas PageRender, yang dapat kita timpa di kelas code-behind kita dengan tanda tangan metode berikut:

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
   ' Add code to manipulate the GridView control hierarchy
   MyBase.Render(writer)
End Sub

Page Ketika metode asli Render kelas dipanggil base.Render(writer) masing-masing kontrol di halaman akan dirender, menghasilkan markup berdasarkan hierarki kontrol mereka. Oleh karena itu sangat penting bahwa kita berdua memanggil base.Render(writer), sehingga halaman dirender, dan bahwa kita memanipulasi hierarki kontrol GridView sebelum memanggil base.Render(writer), sehingga baris pemisah telah ditambahkan ke hierarki kontrol GridView sebelum dirender.

Untuk menyuntikkan header grup pengurutan, pertama-tama kita perlu memastikan bahwa pengguna telah meminta agar data diurutkan. Secara default, konten GridView tidak diurutkan, dan oleh karena itu kita tidak perlu memasukkan header pengurutan grup apa pun.

Nota

Jika Anda ingin GridView diurutkan berdasarkan kolom tertentu saat halaman pertama kali dimuat, panggil metode GridView pada kunjungan pertama halaman (tetapi tidak pada postback berikutnya). Untuk mencapai hal ini, tambahkan panggilan ini di penanganan acara Page_Load dalam sebuah pernyataan bersyarat if (!Page.IsPostBack). Lihat kembali informasi tutorial Halaman dan Pengurutan Data Laporan untuk informasi selengkapnya tentang metode .Sort

Dengan asumsi bahwa data telah diurutkan, tugas kami berikutnya adalah menentukan kolom apa yang diurutkan oleh data lalu untuk memindai baris yang mencari perbedaan dalam nilai kolom tersebut. Kode berikut memastikan bahwa data telah diurutkan dan menemukan kolom tempat data telah diurutkan:

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
    ' Only add the sorting UI if the GridView is sorted
    If Not String.IsNullOrEmpty(ProductList.SortExpression) Then
        ' Determine the index and HeaderText of the column that
        'the data is sorted by
        Dim sortColumnIndex As Integer = -1
        Dim sortColumnHeaderText As String = String.Empty
        For i As Integer = 0 To ProductList.Columns.Count - 1
            If ProductList.Columns(i).SortExpression.CompareTo( _
                ProductList.SortExpression) = 0 Then
                sortColumnIndex = i
                sortColumnHeaderText = ProductList.Columns(i).HeaderText
                Exit For
            End If
        Next
        ' TODO: Scan the rows for differences in the sorted column�s values
End Sub

Jika GridView belum diurutkan, properti dari GridView SortExpression belum diatur. Oleh karena itu, kita hanya ingin menambahkan baris pemisah jika properti ini memiliki beberapa nilai. Jika ya, kita selanjutnya perlu menentukan indeks kolom tempat data diurutkan. Cara ini dilakukan dengan melakukan iterasi pada koleksi Columns GridView, mencari kolom yang propertinya SortExpression sama dengan properti SortExpression GridView. Selain indeks kolom s, kami juga mengambil HeaderText properti , yang digunakan saat menampilkan baris pemisah.

Dengan indeks kolom tempat data diurutkan, langkah terakhir adalah menghitung baris GridView. Untuk setiap baris, kita perlu menentukan apakah nilai dari kolom yang diurutkan berbeda dari nilai kolom yang diurutkan pada baris sebelumnya. Jika demikian, kita perlu menyuntikkan instans baru GridViewRow ke dalam hierarki kontrol. Ini dicapai dengan kode berikut:

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
    ' Only add the sorting UI if the GridView is sorted
    If Not String.IsNullOrEmpty(ProductList.SortExpression) Then
        ' ... Code for finding the sorted column index removed for brevity ...
        ' Reference the Table the GridView has been rendered into
        Dim gridTable As Table = CType(ProductList.Controls(0), Table)
        ' Enumerate each TableRow, adding a sorting UI header if
        ' the sorted value has changed
        Dim lastValue As String = String.Empty
        For Each gvr As GridViewRow In ProductList.Rows
            Dim currentValue As String = gvr.Cells(sortColumnIndex).Text
            If lastValue.CompareTo(currentValue) <> 0 Then
                ' there's been a change in value in the sorted column
                Dim rowIndex As Integer = gridTable.Rows.GetRowIndex(gvr)
                ' Add a new sort header row
                Dim sortRow As New GridViewRow(rowIndex, rowIndex, _
                    DataControlRowType.DataRow, DataControlRowState.Normal)
                Dim sortCell As New TableCell()
                sortCell.ColumnSpan = ProductList.Columns.Count
                sortCell.Text = String.Format("{0}: {1}", _
                    sortColumnHeaderText, currentValue)
                sortCell.CssClass = "SortHeaderRowStyle"
                ' Add sortCell to sortRow, and sortRow to gridTable
                sortRow.Cells.Add(sortCell)
                gridTable.Controls.AddAt(rowIndex, sortRow)
                ' Update lastValue
                lastValue = currentValue
            End If
        Next
    End If
    MyBase.Render(writer)
End Sub

Kode ini dimulai dengan mereferensikan objek yang Table ditemukan secara terprogram di akar hierarki kontrol GridView dan membuat variabel string bernama lastValue. lastValue digunakan untuk membandingkan nilai kolom yang diurutkan dari baris saat ini dengan nilai dari baris sebelumnya. Selanjutnya, koleksi Rows pada GridView diiterasi, dan untuk setiap baris, nilai dari kolom yang diurutkan disimpan ke dalam variabel currentValue.

Nota

Untuk menentukan nilai baris tertentu dari kolom yang diurutkan, saya menggunakan properti sel pada s Text. Ini berfungsi dengan baik untuk BoundFields, tetapi tidak akan berfungsi seperti yang diinginkan untuk TemplateFields, CheckBoxFields, dan sebagainya. Kita akan segera melihat cara memperhitungkan bidang GridView alternatif.

Variabel currentValue dan lastValue kemudian dibandingkan. Jika berbeda, kita perlu menambahkan baris pemisah baru ke hierarki kontrol. Ini dicapai dengan menentukan indeks GridViewRow dalam koleksi Table objek, kemudian membuat instans baru Rows dan GridViewRow, lalu menambahkan TableCell dan TableCell ke dalam hierarki kontrol.

Perhatikan bahwa baris pemisah TableCell saja diformat sedemikian rupa sehingga mencakup seluruh lebar GridView, menggunakan kelas CSS SortHeaderRowStyle, dan memiliki propertinya Text sedemikian rupa sehingga menunjukkan baik nama grup pengurutan (seperti Kategori) maupun nilai grup (seperti Minuman). Terakhir, lastValue diperbarui ke nilai currentValue.

Kelas CSS yang digunakan untuk memformat baris SortHeaderRowStyle header grup pengurutan perlu ditentukan dalam Styles.css file. Jangan ragu untuk menggunakan pengaturan gaya apa pun yang menarik untuk Anda; Saya menggunakan yang berikut:

.SortHeaderRowStyle
{
    background-color: #c00;
    text-align: left;
    font-weight: bold;
    color: White;
}

Dengan kode saat ini, antarmuka pengurutan menambahkan header grup pengurutan saat mengurutkan menurut BoundField apa pun (lihat Gambar 5, yang menunjukkan cuplikan layar saat mengurutkan menurut pemasok). Namun, saat mengurutkan menurut jenis bidang lain (seperti CheckBoxField atau TemplateField), header grup pengurutan tidak dapat ditemukan (lihat Gambar 6).

Antarmuka Pengurutan Menyertakan Header Grup Pengurutan Saat Pengurutan Berdasarkan BoundFields

Gambar 5: Antarmuka Pengurutan Menyertakan Header Kelompok Saat Menyortir Berdasarkan BoundFields (Klik untuk melihat gambar ukuran penuh)

Header Grup Pengurutan Tidak Ada Saat Mengurutkan CheckBoxField

Gambar 6: Header Grup Pengurutan Hilang Saat Mengurutkan CheckBoxField (Klik untuk melihat gambar ukuran penuh)

Alasan mengapa header grup pengurutan hilang saat mengurutkan menurut CheckBoxField adalah karena saat ini kode hanya menggunakan properti TableCell s Text untuk menentukan nilai kolom yang diurutkan untuk setiap baris. Untuk CheckBoxFields, properti TableCells Text adalah string kosong; sebagai gantinya, nilai tersebut dapat diakses melalui kontrol Web CheckBox yang terletak dalam koleksi TableCells Controls.

Untuk menangani jenis bidang selain BoundFields, kita perlu menambahkan kode di mana variabel currentValue ditugaskan untuk memeriksa adanya CheckBox dalam koleksi TableCell s Controls. Alih-alih menggunakan currentValue = gvr.Cells(sortColumnIndex).Text, ganti kode ini dengan yang berikut:

Dim currentValue As String = String.Empty
If gvr.Cells(sortColumnIndex).Controls.Count > 0 Then
    If TypeOf gvr.Cells(sortColumnIndex).Controls(0) Is CheckBox Then
        If CType(gvr.Cells(sortColumnIndex).Controls(0), CheckBox).Checked Then
            currentValue = "Yes"
        Else
            currentValue = "No"
        End If
        ' ... Add other checks here if using columns with other
        '      Web controls in them (Calendars, DropDownLists, etc.) ...
    End If
Else
    currentValue = gvr.Cells(sortColumnIndex).Text
End If

Kode ini memeriksa kolom TableCell yang diurutkan pada baris saat ini untuk menentukan apakah ada kontrol dalam kumpulan Controls. Jika ada, dan kontrol pertama adalah Kotak Centang, currentValue variabel diatur ke Ya atau Tidak, tergantung pada properti Kotak Centang Checked . Jika tidak, nilai diambil dari properti TableCell s Text. Logika ini dapat direplikasi untuk menangani pengurutan untuk TemplateFields apa pun yang mungkin ada di GridView.

Dengan penambahan kode di atas, header kelompok pengurutan sekarang muncul saat mengurutkan berdasarkan CheckBoxField Discontinued (lihat Gambar 7).

Header Grup Sortir Sekarang Ada Saat Mengurutkan CheckBoxField

Gambar 7: Header Grup Urutkan Sekarang Ada Saat Mengurutkan CheckBoxField (Klik untuk melihat gambar ukuran penuh)

Nota

Jika Anda memiliki produk dengan NULL nilai database untuk CategoryIDbidang , , SupplierIDatau , nilai UnitPrice tersebut akan muncul sebagai string kosong di GridView secara default, yang berarti teks baris pemisah untuk produk tersebut dengan NULL nilai akan dibaca seperti Kategori: (yaitu, tidak ada nama setelah Kategori: seperti dengan Kategori: Minuman ). Jika Anda ingin nilai ditampilkan di sini, Anda dapat mengatur properti BoundFields NullDisplayText ke teks yang ingin Anda tampilkan atau Anda dapat menambahkan pernyataan kondisi di metode Render saat menetapkan currentValue ke properti baris pemisahText.

Ringkasan

GridView tidak menyertakan banyak opsi bawaan untuk menyesuaikan antarmuka pengurutan. Namun, dengan sedikit kode tingkat rendah, dimungkinkan untuk mengubah hierarki kontrol GridView untuk membuat antarmuka yang lebih disesuaikan. Dalam tutorial ini kita melihat cara menambahkan baris pemisah grup pengurutan untuk GridView yang dapat diurutkan, yang lebih mudah mengidentifikasi grup yang berbeda dan batas-batas grup tersebut. Untuk contoh tambahan antarmuka pengurutan yang disesuaikan, lihat entri blog Scott Guthrie s A Few ASP.NET 2.0 GridView Sorting Tips dan Tricks .

Selamat Pemrograman!

Tentang Penulis

Scott Mitchell, penulis tujuh buku ASP/ASP.NET dan pendiri 4GuysFromRolla.com, telah bekerja sama dengan teknologi Microsoft Web sejak 1998. Scott bekerja sebagai konsultan, pelatih, dan penulis independen. Buku terbarunya adalah Sams Teach Yourself ASP.NET 2.0 dalam 24 Jam. Dia dapat dijangkau di mitchell@4GuysFromRolla.com.