Untuk hampir semua aplikasi web presentasi data, mengatur cara data ditampilkan dan menghindari perasaan membingungkan bagi pengguna adalah salah satu tujuan utamanya. Menampilkan 20 catatan per halaman tentu dapat diterima, namun menampilkan 10.000 catatan per halaman dapat dengan mudah menimbulkan ketidaknyamanan bagi pengguna. Memisahkan data menjadi beberapa halaman untuk ditampilkan, yaitu membuat halaman data, adalah cara paling umum untuk mengatasi masalah tersebut.
1. Ikhtisar
ASP.NET sendiri hanya menyediakan satu kontrol yang mendukung paging data, yaitu kontrol paging DataGrid. Namun, lebih cocok digunakan di lingkungan Intranet. Untuk lingkungan Internet, fungsi yang disediakan oleh kontrol paging DataGrid sepertinya tidak cukup untuk membangun aplikasi Web yang fleksibel. Salah satu alasannya adalah bahwa kontrol DataGrid menerapkan pembatasan di mana desainer Web dapat menempatkan kontrol halaman dan tampilan kontrol halaman. Misalnya, kontrol DataGrid tidak mengizinkan penempatan kontrol halaman secara vertikal. Kontrol lain yang dapat memanfaatkan teknologi paging adalah Repeater. Pengembang web dapat menggunakan kontrol Repeater untuk mengonfigurasi metode tampilan data dengan cepat, namun fungsi paging mengharuskan pengembang untuk mengimplementasikannya sendiri. Sumber data terus berubah, dan metode presentasi data sangat bervariasi. Tentu saja akan membuang-buang waktu untuk menyesuaikan kontrol halaman untuk kondisi yang berubah ini. Membangun kontrol halaman universal yang tidak terbatas pada kontrol presentasi tertentu akan sangat membantu menghemat waktu.
Kontrol data universal yang sangat baik tidak hanya menyediakan fungsi paging reguler, namun juga dapat:
⑴ Menyediakan tombol navigasi paging "Halaman Beranda", "Halaman Sebelumnya", "Halaman Berikutnya" dan "Halaman Terakhir".
⑵ Sesuaikan statusnya dengan situasi tampilan data, yaitu memiliki sensitivitas data. Jika kontrol paging diatur untuk menampilkan 10 catatan per halaman, namun sebenarnya hanya ada 9 catatan, maka kontrol halaman tidak boleh ditampilkan ketika data dibagi menjadi beberapa halaman untuk ditampilkan, "Beranda" dan "Atas". halaman pertama Tombol "Halaman" tidak boleh ditampilkan, begitu pula tombol "Halaman Berikutnya" dan "Halaman Terakhir" pada halaman terakhir tidak boleh ditampilkan.
⑶ Tidak dapat mengandalkan kontrol tampilan data tertentu.
⑷ Kemampuan beradaptasi dengan berbagai sumber data yang ada dan yang akan datang.
⑸ Mode tampilan harus mudah dikonfigurasi dan diintegrasikan ke dalam berbagai aplikasi.
⑹ Saat paging sudah siap, ingatkan kontrol lainnya.
⑺ Bahkan desainer web yang tidak berpengalaman pun dapat menggunakannya tanpa kesulitan.
⑻ Memberikan data atribut tentang informasi paging.
Saat ini terdapat beberapa kontrol komersial di pasaran yang menyediakan fungsi di atas, namun semuanya mahal. Bagi banyak pengembang, membuat sendiri kontrol paging universal adalah pilihan ideal.
Gambar 1 menunjukkan antarmuka kontrol paging universal yang berjalan dalam artikel ini, di mana kontrol yang digunakan untuk tampilan adalah kontrol Repeater. Kontrol halaman terdiri dari dua jenis komponen: empat tombol navigasi dan satu set link nomor halaman.
Pengguna dapat dengan mudah mengubah kontrol tampilan dan mengubah tampilan kontrol paging itu sendiri. Misalnya, kontrol tampilan yang bekerja sama dengan kontrol halaman digantikan oleh kontrol DataGrid, dan link nomor halaman serta empat tombol navigasi ditampilkan dalam dua baris.
ASP.NET mendukung tiga cara untuk membuat kontrol Web kustom: kontrol pengguna, kontrol komposit, dan kontrol kustom. Nama tipe kontrol ketiga, kontrol kustom, mudah menyesatkan. Faktanya, ketiga kontrol tersebut harus dianggap sebagai kontrol khusus. Perbedaan antara kontrol komposit dan kontrol khusus Microsoft adalah bahwa kontrol gabungan memerlukan metode CreateChildControls(). Metode CreateChildControls() memungkinkan kontrol untuk menggambar ulang dirinya sendiri berdasarkan peristiwa tertentu. Untuk pager universal artikel ini, kita akan menggunakan kontrol komposit.
Diagram urutan UML berikut menguraikan mekanisme umum kontrol paging universal.
Meskipun tujuan kita adalah membuat kontrol paging universal tidak bergantung pada kontrol yang mewakili data, jelas bahwa harus ada cara agar kontrol halaman dapat mengakses data. Setiap kontrol yang diwarisi dari kelas Kontrol menyediakan peristiwa DataBinding. Kami mendaftarkan pager itu sendiri sebagai pendengar acara DataBinding, sehingga pager dapat mempelajari data dan memodifikasi data. Karena semua kontrol yang mewarisi kelas Kontrol memiliki peristiwa Pengikatan Data ini, kontrol pager mencapai tujuan dengan tidak bergantung pada kontrol presentasi data tertentu - dengan kata lain, kontrol pager dapat diikat ke semua kontrol yang berasal dari kelas Kontrol. Artinya, dapat terikat pada hampir semua kontrol Web.
2. Fungsi inti
Ketika kontrol presentasi memicu peristiwa DataBinding, kontrol paging dapat memperoleh properti DataSource. Sayangnya, Microsoft tidak menyediakan antarmuka yang diterapkan oleh semua kelas pengikatan data, seperti IdataSourceProvider, dan tidak semua kontrol yang diwarisi dari kelas Kontrol atau WebControl memiliki properti DataSource, jadi tidak ada gunanya melakukan upcasting ke kelas Kontrol, satu-satunya yang layak Caranya adalah dengan langsung mengoperasikan properti DataSoruce melalui Reflection API. Sebelum membahas metode event handler, perlu dicatat bahwa untuk mendaftarkan event handler, Anda harus terlebih dahulu mendapatkan referensi ke kontrol presentasi. Kontrol paging memperlihatkan properti string sederhana BindToControl:
string publik BindToControl
{
mendapatkan
{
jika (_bindcontrol == nol)
throw new NullReferenceException("Sebelum menggunakan kontrol paging, harap ikat ke kontrol dengan menyetel properti BindToControl.");
kembalikan _bindcontrol;}
set{_bindcontrol=nilai;}
}
Metode ini sangat penting, jadi yang terbaik adalah menyampaikan pesan yang lebih jelas daripada membuang NullReferenceException standar. Dalam metode OnInit pada kontrol paging, kami menyelesaikan referensi ke kontrol presentasi. Contoh ini harus menggunakan event handler OnInit (bukan konstruktor) untuk memastikan bahwa halaman aspx yang dikompilasi JIT memiliki set BindToControl.
override terproteksi void OnInit(EventArgs e)
{
_boundcontrol = Induk.FindControl(BindToControl);
BoundControl.DataBinding += EventHandler baru(BoundControl_DataBound);
base.OnInit(e);
...
}
Operasi pencarian kontrol presentasi diselesaikan dengan mencari kontrol Induk dari kontrol halaman. Di sini, Induk adalah halaman itu sendiri. Berbahaya menggunakan Induk dengan cara ini. Misalnya, jika kontrol paging tertanam di kontrol lain, misalnya kontrol Tabel, referensi Induk sebenarnya akan menjadi referensi ke kontrol Tabel. Karena metode FindControl hanya mencari koleksi kontrol saat ini, pencarian tidak mungkin dilakukan kecuali kontrol presentasi ada dalam koleksi. Pendekatan yang lebih aman adalah dengan menelusuri kumpulan kontrol secara rekursif hingga kontrol target ditemukan.
Setelah menemukan BoundControl, kami mendaftarkan kontrol paging sebagai pendengar untuk acara DataBinding. Karena kontrol paging beroperasi pada sumber data, penting agar pengendali kejadian ini menjadi yang terakhir dalam rantai panggilan. Namun, selama kontrol presentasi mendaftarkan event handler DataBinding di event handler OnInit (perilaku default), tidak akan ada masalah saat kontrol paging mengoperasikan sumber data.
Pengendali kejadian DataBound bertanggung jawab untuk mendapatkan properti DataSource dari kontrol presentasi.
private void BoundControl_DataBound(pengirim objek,System.EventArgs e)
{
jika (HasParentControlCalledDataBinding) kembali;
Ketik tipe = pengirim.GetType();
_datasource = type.GetProperty("Sumber Data");
jika (_datasource == nol)
throw new NotSupportedException("Kontrol paging mengharuskan kontrol presentasi harus berisi Sumber Data.");
data objek = _datasource.GetGetMethod().Invoke(sender,null);
_builder = Adaptor[data.GetType()];
jika (_pembangun == nol)
throw new NullReferenceException("Adaptor yang sesuai tidak dipasang untuk menangani jenis sumber data berikut: "+data.GetType());
_builder.Sumber = data;
ApplyDataSensitivityRules();
BindParent();
RaiseEvent(Pembaruan Data,ini);
}
Di DataBound, kami mencoba mendapatkan properti DataSource melalui Reflection API dan kemudian mengembalikan referensi ke sumber data sebenarnya. Sekarang setelah sumber data diketahui, kontrol paging juga harus mengetahui cara mengoperasikan sumber data. Untuk membuat kontrol paging tidak bergantung pada kontrol presentasi tertentu, masalahnya jauh lebih rumit. Namun, membuat kontrol halaman bergantung pada sumber data tertentu akan menggagalkan tujuan merancang kontrol halaman yang fleksibel. Kita perlu menggunakan arsitektur plug-in untuk memastikan bahwa kontrol paging dapat menangani berbagai sumber data, baik itu sumber data yang disediakan oleh .NET atau sumber data khusus.
Untuk menyediakan arsitektur pluggable yang kuat dan terukur, kami akan membangun solusi menggunakan pola [GoF] Builder.
Gambar 4
Antarmuka IDataSourceAdapter mendefinisikan elemen paling dasar yang diperlukan untuk kontrol paging untuk mengoperasikan data, yang setara dengan "plug".
antarmuka publik IDataSourceAdapter
{
int TotalHitungan{dapatkan;}
objek GetPagedData(int awal,int akhir);
}
Properti TotalCount mengembalikan jumlah total elemen yang terdapat dalam sumber data sebelum memproses data, sedangkan metode GetPagedData mengembalikan subset data asli. Misalnya: dengan asumsi sumber data adalah array yang berisi 20 elemen, kontrol paging akan ditampilkan data sebagai 10 elemen per halaman elemen, maka subset elemen pada halaman pertama adalah elemen array 0-9, dan subset elemen pada halaman kedua adalah elemen array 10-19. DataViewAdapter menyediakan plug tipe DataView:
kelas internal DataViewAdapter:IDataSourceAdapter
{
DataView pribadi _view;
DataViewAdapter internal (tampilan DataView)
{
_view = melihat;
}
publik ke TotalCount
{
dapatkan{return (_view == null) 0 : _view.Table.Rows.Count;}
}
objek publik GetPagedData(int awal, int akhir)
{
Tabel DataTable = _view.Table.Clone();
untuk (int i = start;i<=end && i<= TotalCount;i++)
{
tabel.ImportRow(_view[i-1].Row);
}
meja pengembalian;
}
}
DataViewAdapter mengimplementasikan metode GetPagedData dari IDataSourceAdapter, yang mengkloning DataTable asli dan mengimpor data dalam DataTable asli ke dalam DataTable baru. Visibilitas kelas ini sengaja disetel ke internal untuk menyembunyikan detail implementasi dari pengembang web dan menyediakan antarmuka yang lebih sederhana melalui kelas Builder.
AdapterBuilder kelas abstrak publik
{
objek pribadi _source;
kekosongan pribadi CheckForNull()
{
if (_source == null) throw new NullReferenceException("Sumber data legal harus disediakan");
}
Sumber objek virtual publik
{
mendapatkan
{
PeriksaForNull();
kembalikan _sumber;}
mengatur
{
_sumber = nilai;
PeriksaForNull();
}
}
Adaptor IDataSourceAdapter abstrak publik{get;}
}
Kelas abstrak AdapterBuilder menyediakan antarmuka yang lebih mudah dikelola untuk tipe IdataSourceAdapter. Karena peningkatan level abstraksi, kita tidak lagi harus menggunakan IdataSourceAdapter secara langsung. Pada saat yang sama, AdapterBuilder juga menyediakan instruksi untuk melakukan pra-pemrosesan sebelum melakukan paging data. Selain itu, Builder ini juga menjadikan kelas implementasi aktual, seperti DataViewAdapter, transparan bagi pengguna kontrol paging:
public class DataTableAdapterBuilder:AdapterBuilder
{
DataViewAdapter _adapter pribadi;
DataViewAdapter ViewAdapter pribadi
{
mendapatkan
{
jika (_adaptor == nol)
{
Tabel DataTable = (DataTable)Sumber;
_adapter = DataViewAdapter baru(tabel.DefaultView);
}
kembalikan _adaptor;
}
}
penggantian publik Adaptor IDataSourceAdapter
{
mendapatkan
{
kembalikan ViewAdapter;
}
}
}
kelas publik DataViewAdapterBuilder:AdapterBuilder
{
DataViewAdapter _adapter pribadi;
DataViewAdapter ViewAdapter pribadi
{
mendapatkan
{// Instansiasi tertunda
jika (_adaptor == nol)
{
_adapter = new DataViewAdapter((DataView)Sumber);
}
kembalikan _adaptor;
}
}
penggantian publik Adaptor IDataSourceAdapter
{
dapatkan{kembalikan ViewAdapter;}
}
}
Tipe DataView dan tipe DataTable sangat erat kaitannya sehingga masuk akal untuk membuat DataAdapter generik. Sebenarnya, menambahkan konstruktor lain yang menangani DataTable saja sudah cukup. Sayangnya, ketika pengguna memerlukan fungsionalitas berbeda untuk menangani DataTable, seluruh kelas harus diganti atau diwarisi. Jika kita membuat Builder baru yang menggunakan IdataSourceAdapter yang sama, pengguna memiliki lebih banyak kebebasan dalam memilih cara mengimplementasikan adaptor.
Dalam kontrol paging, operasi pencarian kelas Builder yang sesuai diselesaikan dengan koleksi tipe-aman.
Koleksi Adaptor kelas publik:DictionaryBase
{
string pribadi GetKey (Ketik kunci)
{
kunci kembali.Nama Lengkap;
}
AdapterCollection publik() {}
publicvoid Tambah (Ketik kunci, nilai AdapterBuilder)
{
Kamus.Tambahkan(GetKey(kunci),nilai);
}
publicbool Berisi (Ketik kunci)
{
return Dictionary.Contains(GetKey(kunci));
}
publicvoid Hapus (Ketik kunci)
{
Kamus.Hapus(GetKey(kunci));
}
publik AdapterBuilder ini[Ketik kunci]
{
get{return (AdapterBuilder)Kamus[GetKey(kunci)];}
set{Kamus[GetKey(kunci)]=nilai;}
}
}
AdapterCollection bergantung pada tipe DataSource, dan DataSource secara cerdik diperkenalkan melalui BoundControl_DataBound. Kunci indeks yang digunakan di sini adalah metode Type.FullName, yang memastikan keunikan kunci indeks setiap jenis. Pada saat yang sama, metode ini juga memberikan tanggung jawab untuk memastikan bahwa hanya ada satu Pembangun untuk setiap jenis ke AdapterCollection. Tambahkan pencarian Builder ke metode BoundControl_DataBound dan hasilnya sebagai berikut:
public AdapterCollection Adapters
{
dapatkan{kembalikan _adapters;}
}
bool pribadi HasParentControlCalledDataBinding
{
dapatkan{kembalikan _pembangun != null;}
}
private void BoundControl_DataBound(pengirim objek,System.EventArgs e)
{
jika (HasParentControlCalledDataBinding) kembali;
Ketik tipe = pengirim.GetType();
_datasource = type.GetProperty("Sumber Data");
jika (_datasource == nol)
throw new NotSupportedException("Kontrol paging mengharuskan kontrol presentasi harus berisi Sumber Data.");
data objek = _datasource.GetGetMethod().Invoke(sender,null);
_builder = Adaptor[data.GetType()];
jika (_pembangun == nol)
throw new NullReferenceException("Adaptor yang sesuai tidak dipasang untuk menangani jenis sumber data berikut: "+data.GetType());
_builder.Sumber = data;
ApplyDataSensitivityRules();
BindParent();
RaiseEvent(Pembaruan Data,ini);
}
Metode BoundControl_DataBound menggunakan HasParentControlCalledDataBinding untuk memeriksa apakah Builder telah dibuat. Jika demikian, maka Builder tidak akan lagi melakukan operasi pencarian Builder yang sesuai. Inisialisasi tabel Adaptor dilakukan di konstruktor:
public Pager()
{
SelectedPager=Sistem.Web.UI.WebControls.Style() baru;
UnselectedPager = Sistem.Web.UI.WebControls.Style() baru;
_adapters = AdapterCollection baru();
_adapters.Add(typeof(DataTable),DataTableAdapterBuilder());
_adapters.Add(typeof(DataView),DataViewAdapterBuilder());
}
Metode terakhir yang diterapkan adalah BindParent yang digunakan untuk memproses dan mengembalikan data.
kekosongan pribadi BindParent()
{
_datasource.GetSetMethod().Panggil(BoundControl,
objek baru[]{_builder.Adapter.GetPagedData(StartRow,ResultsToShow*CurrentPage)});
}
Cara ini sangat sederhana, karena pengolahan data sebenarnya dilakukan oleh Adaptor. Setelah proses ini selesai, kita akan menggunakan Reflection API lagi, namun kali ini untuk menyetel properti DataSource pada kontrol presentasi.
3. Desain Antarmuka
Sejauh ini, fungsi inti dari kontrol paging hampir diterapkan, namun jika metode presentasi yang kurang tepat, kontrol paging tidak akan terlalu berguna.
Untuk memisahkan metode presentasi dari logika program secara efektif, cara terbaik adalah menggunakan templat, atau lebih spesifiknya, menggunakan antarmuka Itemplate. Faktanya, Microsoft dengan jelas memahami kekuatan templat dan menggunakannya hampir di mana saja, bahkan di pengurai halaman itu sendiri. Sayangnya, template bukanlah konsep yang sederhana seperti yang dipikirkan sebagian orang, dan perlu waktu untuk benar-benar memahami esensinya. Untungnya, ada banyak informasi di bidang ini, jadi saya tidak akan membahas detailnya di sini. Kembali ke kontrol paging, ia memiliki empat tombol: halaman beranda, halaman sebelumnya, halaman berikutnya, halaman terakhir, dan tentu saja nomor setiap halaman. Keempat tombol navigasi dipilih dari kelas ImageButton daripada kelas LinkButton. Dari perspektif desain Web profesional, tombol grafis jelas lebih berguna daripada tautan monoton.
public ImageButton FirstButton{dapatkan {return First;}}
public ImageButton LastButton{dapatkan {return Last;}}
public ImageButton PreviousButton{dapatkan {return Previous;}}
public ImageButton NextButton{get {return Next;}}
Nomor halaman dibuat secara dinamis karena bergantung pada jumlah record dalam sumber data dan jumlah record yang ditampilkan pada setiap halaman. Nomor halaman akan ditambahkan ke Panel, dan desainer web dapat menggunakan Panel untuk menentukan tempat menampilkan nomor halaman. Proses pembuatan nomor halaman akan dibahas secara detail nanti. Sekarang kita perlu menyediakan template untuk kontrol paging sehingga pengguna dapat menyesuaikan tampilan kontrol paging.
[Kontainer Templat(typeof(LayoutContainer))]
Tata Letak ITemplate publik
{
dapatkan{kembali (_layout;}
atur{_layout =nilai;}
}
kelas publik LayoutContainer:Kontrol,INamingContainer
{
publicLayoutContainer()
{ini.ID = "Halaman";}
}
Kelas LayoutContainer menyediakan wadah untuk templat. Secara umum, sebaiknya tambahkan ID khusus ke penampung templat, yang akan menghindari masalah saat menangani peristiwa dan membuat panggilan halaman. Diagram UML berikut menjelaskan mekanisme presentasi kontrol paging.
Gambar 5
Langkah pertama dalam membuat template adalah menentukan layout pada halaman aspx:
< TATA LETAK >
<asp:ImageButton id="Pertama" Runat="server" imageUrl="play2L_dis.gif"
AlternateText="Beranda"></asp:ImageButton>
<asp:ImageButton id="Sebelumnya" Runat="server" imageUrl="play2L.gif"
AlternateText="Halaman sebelumnya"></asp:ImageButton>
<asp:ImageButton id="Berikutnya" Runat="server" imageUrl="play2.gif"
AlternateText="Halaman berikutnya"></asp:ImageButton>
<asp:ImageButton id="Terakhir" Runat="server" imageUrl="play2_dis.gif"
AlternateText="Halaman terakhir"></asp:ImageButton>
<asp:Panel id="Pager" Runat="server"></asp:Panel>
</LAYOUT>
Contoh tata letak ini tidak mengandung elemen format apa pun, seperti tabel, dll. Tentu saja, aplikasi sebenarnya dapat (dan harus) menambahkan elemen format, silakan lihat petunjuk lebih lanjut nanti.
Antarmuka Itemplate hanya menyediakan satu metode InstantiateIn, yang mem-parsing template dan mengikat container.
kekosongan pribadi InstantiateTemplate()
{
_container = LayoutContainer baru();
Tata Letak.InstantiateIn(_container);
Pertama = (ImageButton)_container.FindControl("Pertama");
Sebelumnya = (ImageButton)_container.FindControl("Sebelumnya");
Berikutnya = (ImageButton)_container.FindControl("Berikutnya");
Terakhir = (ImageButton)_container.FindControl("Terakhir");
Pemegang = (Panel)_container.FindControl("Pager");
ini.Klik Pertama.+= Sistem.Web.UI.ImageClickEventHandler baru(ini.Klik_Pertama);
this.Last.Click += Sistem.Web.UI.ImageClickEventHandler(this.Last_Click) baru;
ini.Berikutnya.Klik += Sistem.Web.UI.ImageClickEventHandler baru(ini.Klik_Berikutnya);
ini.Sebelumnya.Klik += Sistem.Web.UI.ImageClickEventHandler baru(ini.Klik_Sebelumnya);
}
Hal pertama yang dilakukan metode InstatiateTemplate kontrol adalah membuat instance template, yaitu memanggil Layout.InstantiateIn(_container). Wadah sebenarnya adalah sejenis kontrol, dan penggunaannya mirip dengan kontrol lainnya. Metode InstantiateTemplate menggunakan fitur ini untuk menemukan empat tombol navigasi dan Panel yang digunakan untuk menampung nomor halaman. Tombol navigasi ditemukan berdasarkan ID-nya. Ini adalah batasan kecil pada kontrol paging: tombol navigasi harus memiliki ID yang ditentukan, yaitu Pertama, Sebelumnya, Berikutnya, dan Terakhir. Selain itu, ID Panel harus Pager, jika tidak maka akan Bukan ditemukan. Sayangnya, ini tampaknya merupakan pendekatan yang lebih baik untuk mekanisme presentasi yang kami pilih, namun mudah-mudahan, dengan dokumentasi yang tepat, batasan kecil ini tidak akan menimbulkan masalah. Alternatif lain adalah membiarkan setiap tombol mewarisi dari kelas ImageButton, sehingga mendefinisikan tipe baru karena setiap tombol adalah tipe yang berbeda, pencarian rekursif dapat diterapkan dalam wadah untuk menemukan Berbagai tombol spesifik, sehingga menghilangkan kebutuhan untuk menggunakan ID tombol; atribut.
Setelah Anda menemukan keempat tombol, ikat event handler yang sesuai ke tombol tersebut. Keputusan penting harus diambil disini, yaitu kapan memanggil InstantiateTemplate. Secara umum, metode jenis ini harus dipanggil dalam metode CreateChildControls, karena tujuan utama metode CreateChildControls adalah jenis tugas membuat kontrol anak. Karena kontrol halaman tidak pernah mengubah kontrol turunannya, maka kontrol tersebut tidak memerlukan fungsionalitas yang disediakan oleh CreateChildControls untuk mengubah status tampilan berdasarkan beberapa peristiwa. Semakin cepat kontrol anak ditampilkan, semakin baik, sehingga tempat ideal untuk memanggil metode InstantiateTemplate adalah di event OnInit.
penggantian terproteksi void OnInit(EventArgs e)
{
_boundcontrol = Induk.FindControl(BindToControl);
BoundControl.DataBinding += EventHandler baru(BoundControl_DataBound);
Templat Instansiasi();
Kontrol.Tambahkan(_container);
base.OnInit(e);
}
Selain memanggil metode InstantiateTemplate, metode OnInit juga memiliki tugas penting lainnya yaitu menambahkan container ke kontrol paging. Jika Anda tidak menambahkan wadah ke koleksi kontrol pager, templat tidak akan ditampilkan karena metode Render tidak akan pernah dipanggil.
Template juga dapat didefinisikan secara terprogram dengan mengimplementasikan antarmuka Itemplate. Selain sebagai ukuran untuk meningkatkan fleksibilitas, fitur ini juga dapat menyediakan template default untuk digunakan ketika pengguna tidak menyediakan template melalui halaman aspx.
kelas publik DefaultPagerLayout:ITemplate
{
ImageButton pribadi Berikutnya;
ImageButton pribadi Pertama;
ImageButton pribadi Terakhir;
ImageButton pribadi Sebelumnya;
Pager Panel pribadi;
DefaultPagerLayout() publik
{
Berikutnya = ImageButton baru();
Pertama = New ImageButton();
Terakhir = New ImageButton();
Sebelumnya = ImageButton baru();
Pager = Panel baru();
Berikutnya.ID="Berikutnya"; Berikutnya.AlternateText="Halaman berikutnya";Berikutnya.ImageUrl="play2.gif";
Pertama.ID="Pertama"; Pertama.AlternateText="Beranda";Pertama.ImageUrl="play2L_dis.gif";
Last.ID = "Terakhir"; Last.AlternateText = "Halaman terakhir"; Last.ImageUrl="play2_dis.gif";
Sebelumnya.ID="Sebelumnya"; Sebelumnya.AlternateText="Halaman Sebelumnya";Sebelumnya.ImageUrl="play2L.gif";
Pager.ID="Halaman";
}
public void InstantiateIn(Kontrol kontrol)
{
kontrol.Kontrol.Hapus();
Tabel tabel = Tabel baru();
tabel.BorderWidth = Unit.Pixel(0);
tabel.Spasi Sel= 1;
tabel.CellPadding =0;
Baris TableRow = TableRow baru();
baris.VerticalAlign = VerticalAlign.Top;
tabel.Baris.Tambahkan(baris);
Sel TableCell = TableCell baru();
sel.HorizontalAlign = HorizontalAlign.Kanan;
sel.VerticalAlign = VerticalAlign.Middle;
sel.Kontrol.Tambahkan(Pertama);
sel.Kontrol.Tambahkan(Sebelumnya);
baris.Sel.Tambahkan(sel);
sel = TableCell baru();
sel.HorizontalAlign= HorizontalAlign.Center;
sel.Kontrol.Tambahkan(Pager);
baris.Sel.Tambahkan(sel);
sel = TableCell baru();
sel.VerticalAlign = VerticalAlign.Middle;
sel.Kontrol.Tambahkan(Berikutnya);
sel.Kontrol.Tambahkan(Terakhir);
baris.Sel.Tambahkan(sel);
kontrol.Kontrol.Tambahkan(tabel);
}
}
DefaultPagerLayout menyediakan semua elemen navigasi secara terprogram dan menambahkannya ke halaman aspx, namun kali ini elemen navigasi diformat dengan tabel HTML standar. Nah, jika pengguna tidak menyediakan template presentasi, program akan otomatis menyediakan template default.
[TemplateContainer(typeof(LayoutContainer))]
Tata Letak ITemplate publik
{
dapatkan{return (_layout == null)? DefaultPagerLayout():_layout;} baru
atur{_layout =nilai;}
}
Mari kita lihat proses menghasilkan setiap nomor halaman. Kontrol paging pertama-tama perlu menentukan beberapa nilai properti, dan menggunakan nilai properti ini untuk menentukan berapa banyak nomor halaman berbeda yang akan dihasilkan.
publik int Halaman Saat Ini
{
mendapatkan
{
string cur = (string)ViewState["Halaman Saat Ini"];
kembali (skr == string.Kosong || skr ==null) 1 : int.Parse(skr);
}
mengatur
{
ViewState["CurrentPage"] = nilai.ToString();}
}
int publik PagersToShow
{
dapatkan{kembalikan _hasil;}
set{_hasil = nilai;}
}
int publik HasilToShow
{
dapatkan{kembalikan _hasilperhalaman;}
set{_resultsperpage = nilai;}
}
CurrentPage sebenarnya menyimpan halaman saat ini dalam ViewState dari nomor halaman. Properti yang ditentukan oleh metode PagersToShow memungkinkan pengguna untuk menentukan berapa banyak halaman yang akan ditampilkan, sedangkan properti yang ditentukan oleh ResultsToShow memungkinkan pengguna untuk menentukan berapa banyak catatan yang akan ditampilkan. setiap halaman. Nilai defaultnya adalah 10.
NumberofPagersToGenerate mengembalikan jumlah nomor halaman saat ini yang harus dihasilkan.
Urutan Pager int pribadi
{
mendapatkan
{
kembalikan Konversi.ToInt32
(Math.Ceiling((double)CurrentPage/(double)PagersToShow));}
}
int pribadi NumberOfPagersToGenerate
{
dapatkan{return PagerSequence*PagersToShow;}
}
pribadi ke dalam TotalPagesToShow
{
get{return Convert.ToInt32(Math.Ceiling((double)TotalResults/(double)_resultsperpage));}
}
publik int Hasil Total
{
dapatkan{return _builder.Adapter.TotalCount;}
}
Metode TotalPagesToShow mengembalikan jumlah total halaman yang akan ditampilkan, disesuaikan dengan properti ResultsToShow yang telah ditetapkan sebelumnya oleh pengguna.
Meskipun ASP.NET mendefinisikan beberapa gaya default, mereka mungkin tidak terlalu praktis bagi pengguna kontrol paging. Pengguna dapat menyesuaikan tampilan kontrol paging melalui gaya khusus.
Gaya publik UnSelectedPagerStyle {dapatkan {return UnselectedPager;}}
public Style SelectedPagerStyle {get {return SelectedPager;}}
UnSelectedPagerStyle menyediakan gaya yang digunakan ketika nomor halaman tidak dipilih, dan SelectedPagerStyle menyediakan gaya yang digunakan ketika nomor halaman dipilih.
kekosongan pribadi GeneratePagers (kontrol WebControl)
{
kontrol.Kontrol.Hapus();
int pager = (PagerSequence-1)* PagersToShow +1;
untuk (;pager<=NumberOfPagersToGenerate && pager<=TotalPagesToShow;pager++)
{
Tautan LinkButton = LinkButton baru();
tautan.Teks = pager.ToString();
link.ID = pager.ToString();
tautan.Klik += EventHandler baru(ini.Pager_Klik);
if (link.ID.Equals(CurrentPage.ToString()))
tautan.MergeStyle(SelectedPagerStyle);
kalau tidak
link.MergeStyle(UnSelectedPagerStyle);
kontrol.Kontrol.Tambahkan(tautan);
control.Controls.Add(new LiteralControl(" "));
}
}
kekosongan pribadi GeneratePagers()
{
HasilkanPagers(Pemegang);
}
Metode GeneratePagers secara dinamis membuat semua nomor halaman, yang merupakan tombol bertipe LinkButton. Atribut label dan ID dari setiap nomor halaman ditetapkan melalui perulangan, dan pada saat yang sama, peristiwa klik terikat ke pengendali peristiwa yang sesuai. Terakhir, nomor halaman ditambahkan ke kontrol kontainer - dalam hal ini, objek Panel. ID tombol berfungsi untuk mengidentifikasi tombol mana yang memicu peristiwa klik. Berikut definisi event handler:
private void Pager_Click(pengirim objek, System.EventArgs e)
{
Tombol LinkButton = (LinkButton) pengirim;
Halaman Saat Ini = int.Parse(tombol.ID);
RaiseEvent(PageChanged, ini, PageChangedEventArgs baru(CurrentPage,PagedEventInvoker.Pager));
Memperbarui();
}
private void Next_Click(pengirim objek, System.Web.UI.ImageClickEventArgs e)
{
if (Halaman Saat Ini<TotalPagesToShow)
Halaman Saat Ini++;
RaiseEvent(PageChanged, ini, PageChangedEventArgs baru(CurrentPage,PagedEventInvoker.Next));
Memperbarui();
}
private void Previous_Click(pengirim objek, System.Web.UI.ImageClickEventArgs e)
{
jika (Halaman Saat Ini> 1)
Halaman Saat Ini--;
RaiseEvent(PageChanged, ini, PageChangedEventArgs baru(CurrentPage,PagedEventInvoker.Previous));
Memperbarui();
}
private void First_Click(pengirim objek, System.Web.UI.ImageClickEventArgs e)
{
Halaman Saat Ini = 1;
RaiseEvent(PageChanged, ini, PageChangedEventArgs baru(CurrentPage,PagedEventInvoker.First));
Memperbarui();
}
private void Last_Click(pengirim objek, System.Web.UI.ImageClickEventArgs e)
{
Halaman Saat Ini = TotalPagesToShow;
RaiseEvent(PageChanged, ini, PageChangedEventArgs baru(CurrentPage,PagedEventInvoker.Last));
Memperbarui();
}
Pengendali kejadian ini serupa karena pertama-tama mereka mengubah halaman saat ini dari kontrol paging dan kemudian menyegarkan kontrol terikat.
Pembaruan kekosongan pribadi()
{
jika (!HasParentControlCalledDataBinding) kembali;
ApplyDataSensitivityRules();
BindParent();
BoundControl.DataBind();
}
Pertama, kontrol paging memeriksa apakah adaptor yang diperlukan telah diinisialisasi dengan memanggil metode HasParentControlCalledDataBinding. Jika demikian, terapkan aturan yang disebutkan sebelumnya untuk menyesuaikan kontrol secara otomatis berdasarkan kondisi tampilan data ke kontrol saat ini. Aturan ini membuat kontrol paging berperilaku berbeda berdasarkan kondisi data yang berbeda di BoundControl. Meskipun aturan-aturan ini dikontrol secara internal oleh kontrol paging, aturan-aturan ini dapat dengan mudah dipindahkan keluar dari kontrol menggunakan mode Status [GoF] bila diperlukan.
bool publik IsDataSensitive
{
dapatkan{kembalikan _isdatasensitif;}
set{_isdatasensitif = nilai;}
}
bool pribadi IsPagerVisible
{
dapatkan{return (TotalPagesToShow != 1) && IsDataSensitive;}
}
bool pribadi IsPreviousVisible
{
mendapatkan
{
kembali (!IsDataSensitive)?
(Halaman Saat Ini!= 1);
}
}
bool pribadi IsNextVisible
{
mendapatkan
{
kembali (!IsDataSensitive)?
(Halaman Saat Ini!= TotalPagesToShow);
}
}
kekosongan pribadi ApplyDataSensitivityRules()
{
FirstButton.Visible = IsPreviousVisible;
PreviousButton.Visible = IsPreviousVisible;
LastButton.Visible = IsNextVisible;
NextButton.Visible = IsNextVisible;
if (IsPagerVisible) GeneratePagers();
}
Metode ApplyDataSensitivityRules mengimplementasikan aturan yang telah ditentukan sebelumnya seperti IsPagerVisible, IsPreviousVisible, dan IsNextVisible. Secara default, kontrol paging akan mengaktifkan aturan ini, namun pengguna dapat menonaktifkannya dengan mengatur properti IsDataSensitive.
Sejauh ini, bagian tampilan dari kontrol paging pada dasarnya telah dirancang. Pekerjaan penyelesaian terakhir yang tersisa adalah menyediakan beberapa event handler sehingga pengguna dapat melakukan penyesuaian yang diperlukan ketika berbagai event kontrol paging terjadi.
delegasi publik batal PageDelegate(pengirim objek,PageChangedEventArgs e);
enum publik PagedEventInvoker{Berikutnya, Sebelumnya, Pertama, Terakhir, Pager}
kelas publik PageChangedEventArgs:EventArgs
{
halaman baru int pribadi;
pemanggil Enum pribadi;
PageChangedEventArgs publik(int halaman baru):base()
{
this.halaman baru = halaman baru;
}
publik PageChangedEventArgs(int halaman baru, pemanggil PagedEventInvoker)
{
this.halaman baru = halaman baru;
this.invoker = pemanggil;
}
public int Halaman Baru {dapatkan{kembalikan halaman baru;}}
public Enum EventInvoker{dapatkan{kembalikan pemanggil;}}
}
Karena kontrol paging perlu mengembalikan parameter peristiwa khusus, kami mendefinisikan kelas PageChangedEventArgs khusus. Kelas PageChangedEventArgs mengembalikan tipe PagedEventInvoker, yang merupakan enumerator kontrol yang dapat memicu kejadian. Untuk menangani parameter peristiwa khusus, kami mendefinisikan delegasi baru, PageDelegate. Acara ini didefinisikan dalam bentuk berikut:
acara publik PageDelegate PageChanged;
public event EventHandler DataUpdate;
Ketika suatu acara tidak memiliki pendengar acara yang sesuai, ASP.NET akan mengeluarkan pengecualian. Kontrol paging mendefinisikan metode RaiseEvent berikut.
private void RaiseEvent(EventHandler e,pengirim objek)
{
this.RaiseEvent(e,ini,null);
}
private void RaiseEvent(EventHandler e,pengirim objek, PageChangedEventArgs args)
{
jika(e!=batal)
{
e(pengirim,args);
}
}
private void RaiseEvent(PageDelegate e,pengirim objek)
{
this.RaiseEvent(e,ini,null);
}
private void RaiseEvent(PageDelegate e,pengirim objek, PageChangedEventArgs args)
{
jika(e!=batal)
{
e(pengirim,args);
}
}
Penangan acara sekarang dapat memicu peristiwa dengan memanggil metode peningkatan individu.
4. Contoh aplikasi
pada titik ini, desain kontrol paging telah selesai dan dapat digunakan secara resmi. Untuk menggunakan kontrol paging, cukup ikat ke kontrol presentasi.
<ASP: Repeater id = "repeater" runat = "server">
<Templat Barang>
Kolom 1:
<%# Convert.toString (databinder.eval (container.dataitem, "column1"))%>
<br>
Kolom 2:
<%# Convert.toString (databinder.eval (container.dataitem, "column2"))%>
<br>
Kolom 3:
<%# Convert.toString (databinder.eval (container.dataitem, "column3"))%>
<br>
<jam>
</Templat Barang>
</ASP: Repeater >
< CC1: pager id = "pager" resultstoshow = "2" runat = "server" bindTocontrol = "repeater" >
< SelectedPagerstyle backcolor = "yellow" />
</CC1: Pager >
Halaman ASPX di atas mengikat kontrol paging ke kontrol repeater, mengatur jumlah catatan yang ditampilkan pada setiap halaman ke 2, warna nomor halaman yang dipilih berwarna kuning, dan menggunakan tata letak default seperti yang ditunjukkan pada Gambar 1. Di bawah ini adalah contoh lain, yang mengikat kontrol paging ke datagrid, seperti yang ditunjukkan pada Gambar 2.
< ASP: datagrid id = "grid" runat = "server" ></asp: datagrid >
< CC1: pager id = "pagergrid" resultstoshow = "2" runat = "server" bindTocontrol = "grid" >
< SelectedPagerstyle backcolor = "Red" ></SelectedPagerstyle >
< tata letak >
< ASP: ImageButton id = "pertama" runat = "server" imageUrl = "play2l_dis.gif" alternateText = "home" ></asp: imageButton >
< ASP: ImageButton ID = "Sebelumnya" runat = "server" ImageUrl = "play2l.gif" alternateText = "halaman sebelumnya" ></asp: ImageButton >
< ASP: ImageButton ID = "Next" Runat = "Server" ImageUrl = "Play2.gif" AlternateText = "Halaman Berikutnya" ></ASP: ImageButton >
< ASP: ImageButton id = "last" runat = "server" ImageUrl = "play2_dis.gif" alternateText = "halaman terakhir" ></asp: imageButton >
< ASP: Panel ID = "pager" runat = "server" ></asp: panel >
</tata letak >
</CC1: Pager >
Tes menunjukkan bahwa kontrol paging tidak tergantung pada kontrol presentasi tertentu. contoh lengkap.
Meskipun belajar kontrol web kustom bukanlah tugas yang mudah, manfaat dari penguasaan keterampilan ini jelas dengan sendirinya. waktu.
http://www.cnblogs.com/niit007/archive/2006/08/13/475501.html