Özelleştirilmiş Sıralama Kullanıcı Arabirimi Oluşturma (C#)
tarafından Scott Mitchell
Sıralanmış verilerin uzun bir listesini görüntülerken, ayırıcı satırlar ekleyerek ilgili verileri gruplandırmak çok yararlı olabilir. Bu öğreticide, böyle bir sıralama kullanıcı arabiriminin nasıl oluşturulacağını göreceğiz.
Giriş
Sıralanmış sütunda yalnızca birkaç farklı değerin bulunduğu uzun bir sıralanmış veri listesi görüntülerken, son kullanıcı fark sınırlarının tam olarak nerede olduğunu ayırt etmek zor olabilir. Örneğin, veritabanında 81 ürün vardır, ancak yalnızca dokuz farklı kategori seçeneği vardır (sekiz benzersiz kategori artı NULL
seçenek). Deniz Ürünleri kategorisine giren ürünleri incelemek isteyen bir kullanıcının durumunu düşünün. Tek bir GridView'daki tüm ürünleri listeleyen bir sayfadan, kullanıcı en iyi sonucunun sonuçları kategoriye göre sıralamak olduğuna karar verebilir ve bu da tüm Deniz Ürünleri ürünlerini birlikte gruplandıracaktır. Kategoriye göre sıraladıktan sonra, kullanıcının deniz ürünleri gruplandırılmış ürünlerin nereden başlayıp sona ereceğini arayarak listede avlanması gerekir. Sonuçlar, Deniz Ürünleri ürünlerini bulmak kategori adına göre alfabetik olarak sıralandığından zor değildir, ancak yine de kılavuzdaki öğelerin listesinin yakından taranması gerekir.
Sıralanmış gruplar arasındaki sınırları vurgulamak için birçok web sitesi, bu gruplar arasında ayırıcı ekleyen bir kullanıcı arabirimini devreye alır. Şekil 1'de gösterilenler gibi ayırıcılar, kullanıcının belirli bir grubu daha hızlı bulmasını, sınırlarını belirlemesini ve verilerde hangi ayrı grupların mevcut olduğunu belirlemesini sağlar.
Şekil 1: Her Kategori Grubu Açıkça Tanımlanmıştır (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Bu öğreticide, böyle bir sıralama kullanıcı arabiriminin nasıl oluşturulacağını göreceğiz.
1. Adım: Standart, Sıralanabilir GridView Oluşturma
Gelişmiş sıralama arabirimi sağlamak için GridView'u nasıl geliştirebileceğimizi keşfetmeden önce, önce ürünleri listeleyen standart, sıralanabilir bir GridView oluşturalım. Klasördeki PagingAndSorting
sayfayı CustomSortingUI.aspx
açarak başlayın. Sayfaya bir GridView ekleyin, özelliğini olarak ProductList
ayarlayın ID
ve yeni bir ObjectDataSource'a bağlayın. ObjectDataSource'ı kayıtları seçmek için sınıfın ProductsBLL
GetProducts()
yöntemini kullanacak şekilde yapılandırın.
Ardından GridView'ı yalnızca , , CategoryName
SupplierName
ve BoundFields ile UnitPrice
Sonlandırılan CheckBoxField değerlerini içerebilecek ProductName
şekilde yapılandırın. Son olarak, GridView'un akıllı etiketindeki Sıralamayı Etkinleştir onay kutusunu işaretleyerek (veya özelliğini olarak ayarlayarak) GridView'ı sıralamayı AllowSorting
destekleyecek şekilde true
yapılandırın. Sayfaya CustomSortingUI.aspx
bu eklemeleri yaptıktan sonra bildirim temelli işaretleme aşağıdakine benzer görünmelidir:
<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>
Şu ana kadarki ilerlememizi bir tarayıcıda görüntülemek için biraz zaman ayırın. Şekil 2'de verileri alfabetik düzende kategoriye göre sıralandığında sıralanabilir GridView gösterilmektedir.
Şekil 2: Sıralanabilir GridView Verileri Kategoriye Göre Sıralandı (Tam boyutlu görüntüyü görüntülemek için tıklayın)
2. Adım: Ayırıcı Satırları Ekleme Tekniklerini Keşfetme
Genel, sıralanabilir GridView tamamlandıktan sonra geriye kalan tek şey, her benzersiz sıralanmış gruptan önce GridView'a ayırıcı satırları ekleyebilmektir. Ancak bu tür satırlar GridView'a nasıl eklenebilir? Temel olarak, GridView satırları arasında yineleme yapmamız, sıralanmış sütundaki değerler arasındaki farkların nerede olduğunu belirlememiz ve ardından uygun ayırıcı satırını eklememiz gerekir. Bu sorun hakkında düşünürken, çözümün GridView RowDataBound
olay işleyicisinde bir yerde olması doğal görünüyor. Verilere Dayalı Özel Biçimlendirme öğreticisinde ele aldığımız gibi, bu olay işleyicisi genellikle satır verilerine göre satır düzeyi biçimlendirme uygulanırken kullanılır. Ancak, RowDataBound
olay işleyicisi burada çözüm değildir, bu olay işleyicisinden GridView'a program aracılığıyla satır eklenemez. Aslında GridView Rows
koleksiyonu salt okunurdur.
GridView'a başka satırlar eklemek için üç seçeneğimiz vardır:
- Bu meta veri ayırıcı satırlarını GridView'a bağlı gerçek verilere ekleyin
- GridView verilere bağlandıktan sonra GridView denetim koleksiyonuna ek
TableRow
örnekler ekleyin - GridView denetimini genişleten ve GridView yapısını oluşturmakla sorumlu olan yöntemleri geçersiz kılan özel bir sunucu denetimi oluşturma
Bu işlev birçok web sayfasında veya çeşitli web sitelerinde gerekliyse, özel bir sunucu denetimi oluşturmak en iyi yaklaşım olacaktır. Bununla birlikte, GridView'un iç çalışmalarının derinliklerine yönelik oldukça fazla kod ve kapsamlı bir inceleme gerektirmektedir. Bu nedenle, bu öğretici için bu seçeneği dikkate almayacağız.
GridView'a bağlı olan gerçek verilere ayırıcı satırlar ekleyen ve GridView'un denetim koleksiyonunu bağlandıktan sonra işlemeye yönelik diğer iki seçenek, soruna farklı şekilde saldırır ve bir tartışmanın üzerine yazar.
GridView'a Bağlı Verilere Satır Ekleme
GridView bir veri kaynağına bağlı olduğunda, veri kaynağı tarafından döndürülen her kayıt için bir GridViewRow
oluşturur. Bu nedenle, GridView'a bağlamadan önce veri kaynağına ayırıcı kayıtlar ekleyerek gerekli ayırıcı satırları ekleyebiliriz. Şekil 3'de bu kavram gösterilmektedir.
Şekil 3: Bir Teknik, Veri Kaynağına Ayırıcı SatırLar Eklemeyi Içerir
Özel ayırıcı kaydı olmadığından tırnak içinde ayırıcı kayıtları terimini kullanıyorum; bunun yerine, veri kaynağındaki belirli bir kaydın normal veri satırı yerine ayırıcı görevi görmesine bir şekilde bayrak eklemeliyiz. Örneklerimiz için bir ProductsDataTable
örneği, 'in ProductRows
oluşturduğu GridView'a bağlayacağız. Bir kaydı ayırıcı satır olarak işaretlemek için -1
özelliğini olarak ayarlayabiliriz CategoryID
(böyle bir değer normal olarak mevcut olmadığından).
Bu tekniği kullanmak için aşağıdaki adımları gerçekleştirmemiz gerekir:
- GridView'a bağlanacak verileri program aracılığıyla alma (örnek
ProductsDataTable
) - GridView'a
SortExpression
veSortDirection
özelliklerine göre verileri sıralama ProductsRows
ProductsDataTable
içinde içinde yineleme yapın ve sıralanmış sütundaki farklılıkların nerede olduğunu arayın- Her grup sınırında, DataTable'a
CategoryID
-1
ayarlanmış bir ayırıcı kayıt örneği ekleyin (veya kaydı ayırıcı kayıtProductsRow
olarak işaretlemeye karar verildiyse) - Ayırıcı satırları ekledikten sonra verileri program aracılığıyla GridView'a bağlayın
Bu beş adıma ek olarak GridView RowDataBound
olayı için bir olay işleyicisi de sağlamamız gerekir. Burada her DataRow
birini denetleyeceğiz ve ayarı olan CategoryID
ayırıcı satır olup olmadığını saptayacağız -1
. Öyleyse, biçimlendirmesini veya hücrelerde görüntülenen metni ayarlamak isteyebiliriz.
Sıralama grubu sınırlarını eklemek için bu tekniği kullanmak için yukarıda belirtilenden biraz daha fazla çalışma gerekir, çünkü GridView Sorting
olayı için bir olay işleyicisi sağlamanız ve ve SortDirection
değerlerini izlemeniz SortExpression
gerekir.
GridView Denetim Koleksiyonunu Veriye Bağlandıktan Sonra Düzenleme
Verileri GridView'a bağlamadan önce mesajlaşmak yerine, veriler GridView'a bağlandıktan sonra ayırıcı satırları ekleyebiliriz. Veri bağlama işlemi GridView denetim hiyerarşisini oluşturur. Bu hiyerarşi gerçekte her biri bir Table
hücre koleksiyonundan oluşan bir satır koleksiyonundan oluşan bir örnektir. Özellikle, GridView denetim koleksiyonu kökünde bir Table
nesne, GridView'a bağlı her kayıt DataSource
için bir GridViewRow
(sınıfından TableRow
türetilir) ve içindeki her veri alanı DataSource
için her GridViewRow
örnekte bir TableCell
nesne içerir.
Her sıralama grubuna ayırıcı satırlar eklemek için, oluşturulduktan sonra bu denetim hiyerarşisini doğrudan işleyebiliriz. GridView denetim hiyerarşisinin, sayfa işlendiğinde son kez oluşturulduğundan emin olabilirsiniz. Bu nedenle, bu yaklaşım sınıfın Page
Render
yöntemini geçersiz kılar ve bu noktada GridView'un son denetim hiyerarşisi gerekli ayırıcı satırları içerecek şekilde güncelleştirilir. Şekil 4'de bu işlem gösterilmektedir.
Şekil 4: Alternatif Bir Teknik GridView Denetim Hiyerarşisini İşleme (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Bu öğreticide, sıralama kullanıcı deneyimini özelleştirmek için bu ikinci yaklaşımı kullanacağız.
Not
Bu öğreticide sunduğum kod, Teemu Keiski'ninGridView Sıralama Gruplandırması ile Biraz Yürütme adlı blog girdisinde sağlanan örneği temel alır.
3. Adım: GridView Denetim Hiyerarşisine Ayırıcı Satırları Ekleme
Ayırıcı satırları yalnızca denetim hiyerarşisi oluşturulduktan ve bu sayfa ziyaretinde son kez oluşturulduktan sonra GridView denetim hiyerarşisine eklemek istediğimizden, bu ekleme işlemini sayfa yaşam döngüsünün sonunda, ancak gerçek GridView denetim hiyerarşisi HTML olarak işlenmeden önce gerçekleştirmek istiyoruz. Bunu gerçekleştirebileceğimiz en son olası nokta, aşağıdaki yöntem imzasını Page
Render
kullanarak arkadaki kod sınıfımızda geçersiz kılabildiğimiz sınıfın olayıdır:
protected override void Render(HtmlTextWriter writer)
{
// Add code to manipulate the GridView control hierarchy
base.Render(writer);
}
Sınıfın Page
özgün Render
yöntemi çağrıldığında base.Render(writer)
sayfadaki denetimlerin her biri işlenir ve denetim hiyerarşisine göre işaretleme oluşturulur. Bu nedenle, her ikimizin de base.Render(writer)
çağrısı yaparak sayfanın işlenmesini ve çağırmadan base.Render(writer)
önce GridView denetim hiyerarşisini işlememiz ve ayırıcı satırların işlenmeden önce GridView denetim hiyerarşisine eklenmesini sağlamak zorunludur.
Sıralama grubu üst bilgilerini eklemek için öncelikle kullanıcının verilerin sıralanmasını istediğinden emin olmamız gerekir. Varsayılan olarak, GridView içeriği sıralanmaz ve bu nedenle grup sıralama üst bilgileri girmemiz gerekmez.
Not
Sayfa ilk yüklendiğinde GridView'un belirli bir sütuna göre sıralanmasını istiyorsanız, ilk sayfa ziyaretinde GridView s Sort
yöntemini çağırın (ancak sonraki geri göndermelerde çağırmayın). Bunu yapmak için, bu çağrıyı bir if (!Page.IsPostBack)
koşullu içindeki olay işleyicisine Page_Load
ekleyin. Yöntemi hakkında daha fazla bilgi için Rapor Verilerini Sayfalama ve Sıralama öğretici bilgilerine Sort
geri bakın.
Verilerin sıralandığını varsayarsak, sıradaki görevimiz verilerin hangi sütuna göre sıralandığını belirlemek ve sonra bu sütunun değerlerindeki farkları bulmak için satırları taramaktır. Aşağıdaki kod, verilerin sıralanmasını sağlar ve verilerin sıralandığı sütunu bulur:
protected override void Render(HtmlTextWriter writer)
{
// Only add the sorting UI if the GridView is sorted
if (!string.IsNullOrEmpty(ProductList.SortExpression))
{
// Determine the index and HeaderText of the column that
//the data is sorted by
int sortColumnIndex = -1;
string sortColumnHeaderText = string.Empty;
for (int i = 0; i < ProductList.Columns.Count; i++)
{
if (ProductList.Columns[i].SortExpression.CompareTo(ProductList.SortExpression)
== 0)
{
sortColumnIndex = i;
sortColumnHeaderText = ProductList.Columns[i].HeaderText;
break;
}
}
// TODO: Scan the rows for differences in the sorted column�s values
}
GridView henüz sıralanmadıysa GridView s SortExpression
özelliği ayarlanmamıştır. Bu nedenle, yalnızca bu özelliğin değeri varsa ayırıcı satırları eklemek istiyoruz. Varsa, bir sonraki adımda verilerin sıralandığı sütunun dizinini belirlememiz gerekir. Bu, GridView koleksiyonunda Columns
döngü oluşturarak ve özelliği GridView s SortExpression
özelliğine eşit olan SortExpression
sütunu arayarak gerçekleştirilir. Sütunun dizinine ek olarak, ayırıcı satırları görüntülerken kullanılan özelliğini de yakalarız HeaderText
.
Verilerin sıralandığı sütunun diziniyle, son adım GridView satırlarını listelemektir. Her satır için sıralanmış sütun değerinin önceki satırın sıralanmış sütun değerinden farklı olup olmadığını belirlememiz gerekir. Öyleyse, denetim hiyerarşisine yeni GridViewRow
bir örnek eklememiz gerekir. Bu, aşağıdaki kodla gerçekleştirilir:
protected override void Render(HtmlTextWriter writer)
{
// Only add the sorting UI if the GridView is sorted
if (!string.IsNullOrEmpty(ProductList.SortExpression))
{
// ... Code for finding the sorted column index removed for brevity ...
// Reference the Table the GridView has been rendered into
Table gridTable = (Table)ProductList.Controls[0];
// Enumerate each TableRow, adding a sorting UI header if
// the sorted value has changed
string lastValue = string.Empty;
foreach (GridViewRow gvr in ProductList.Rows)
{
string currentValue = gvr.Cells[sortColumnIndex].Text;
if (lastValue.CompareTo(currentValue) != 0)
{
// there's been a change in value in the sorted column
int rowIndex = gridTable.Rows.GetRowIndex(gvr);
// Add a new sort header row
GridViewRow sortRow = new GridViewRow(rowIndex, rowIndex,
DataControlRowType.DataRow, DataControlRowState.Normal);
TableCell sortCell = 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;
}
}
}
base.Render(writer);
}
Bu kod, GridView denetim hiyerarşisinin Table
kökünde bulunan nesneye program aracılığıyla başvurarak ve adlı lastValue
bir dize değişkeni oluşturarak başlar. lastValue
geçerli satırın sıralanmış sütun değerini önceki satır değeriyle karşılaştırmak için kullanılır. Ardından GridView koleksiyonu Rows
numaralandırılır ve her satır için sıralanmış sütunun değeri değişkende currentValue
depolanır.
Not
Belirli bir satırın sıralanmış sütununun değerini belirlemek için s hücre Text
özelliğini kullanıyorum. Bu, BoundFields için iyi çalışır, ancak TemplateFields, CheckBoxFields vb. için istenen şekilde çalışmaz. Kısa süre içinde alternatif GridView alanlarını nasıl hesaba ekleyebileceğimizi inceleyeceğiz.
Ardından currentValue
ve lastValue
değişkenleri karşılaştırılır. Bunlar farklıysa, denetim hiyerarşisine yeni bir ayırıcı satırı eklememiz gerekir. Bu, nesnesinin GridViewRow
Rows
koleksiyonundaki Table
dizinini belirleyerek, yeni GridViewRow
ve örnekler oluşturarak ve TableCell
sonra ve GridViewRow
öğesini denetim hiyerarşisine ekleyerek TableCell
gerçekleştirilir.
Ayırıcı satırın yalnızlığının TableCell
GridView'un tüm genişliğine yayılacak şekilde biçimlendirildiğini, CSS sınıfı kullanılarak SortHeaderRowStyle
biçimlendirildiğini ve Text
hem sıralama grubu adını (Kategori gibi) hem de grup değerini (İçecekler gibi) gösteren özelliği olduğunu unutmayın. Son olarak, lastValue
değerine currentValue
güncelleştirilir.
Sıralama grubu üst bilgi satırını SortHeaderRowStyle
biçimlendirmek için kullanılan CSS sınıfının dosyada Styles.css
belirtilmesi gerekir. Size hitap eden stil ayarlarını kullanmaktan çekinmeyin; Aşağıdakileri kullandım:
.SortHeaderRowStyle
{
background-color: #c00;
text-align: left;
font-weight: bold;
color: White;
}
Geçerli kodla, sıralama arabirimi herhangi bir BoundField değerine göre sıralama yaparken sıralama grubu üst bilgileri ekler (sağlayıcıya göre sıralama yaparken ekran görüntüsü gösteren Şekil 5'e bakın). Ancak, başka bir alan türüne (CheckBoxField veya TemplateField gibi) göre sıralama yaparken, sıralama grubu üst bilgileri hiçbir yerde bulunmaz (bkz. Şekil 6).
Şekil 5: Sıralama Arabirimi, BoundFields'a Göre Sıralarken Grup Üst Bilgilerini Sıralar (Tam boyutlu görüntüyü görüntülemek için tıklayın) içerir
Şekil 6: CheckBoxField Sıralanırken Grup Üst Bilgilerini Sırala eksik (Tam boyutlu görüntüyü görüntülemek için tıklayın)
CheckBoxField ölçütüne göre sıralama yaparken sıralama grubu üst bilgilerinin eksik olmasının nedeni, kodun şu anda her satır için sıralanmış sütunun değerini belirlemek için yalnızca TableCell
s Text
özelliğini kullanmasıdır. CheckBoxFields için s TableCell
Text
özelliği boş bir dizedir; bunun yerine, değer s Controls
koleksiyonunda TableCell
bulunan bir CheckBox Web denetimi aracılığıyla kullanılabilir.
BoundFields dışındaki alan türlerini işlemek için değişkenin atandığı currentValue
kodu genişleterek s Controls
koleksiyonunda TableCell
bir CheckBox olup olmadığını denetlememiz gerekir. kullanmak currentValue = gvr.Cells[sortColumnIndex].Text
yerine, bu kodu aşağıdakilerle değiştirin:
string currentValue = string.Empty;
if (gvr.Cells[sortColumnIndex].Controls.Count > 0)
{
if (gvr.Cells[sortColumnIndex].Controls[0] is CheckBox)
{
if (((CheckBox)gvr.Cells[sortColumnIndex].Controls[0]).Checked)
currentValue = "Yes";
else
currentValue = "No";
}
// ... Add other checks here if using columns with other
// Web controls in them (Calendars, DropDownLists, etc.) ...
}
else
currentValue = gvr.Cells[sortColumnIndex].Text;
Bu kod, geçerli satırın sıralanmış sütununu TableCell
inceleyerek koleksiyonda Controls
herhangi bir denetim olup olmadığını belirler. Varsa ve ilk denetim bir CheckBox ise, currentValue
değişken CheckBox s Checked
özelliğine bağlı olarak Evet veya Hayır olarak ayarlanır. Aksi takdirde, değer s Text
özelliğinden TableCell
alınır. Bu mantık, GridView'da mevcut olabilecek tüm TemplateField'ler için sıralamayı işlemek üzere çoğaltılabilir.
Yukarıdaki kod eklemesiyle, artık Sona Erdirilen CheckBoxField ölçütüne göre sıralama yaparken sıralama grubu üst bilgileri mevcuttur (bkz. Şekil 7).
Şekil 7: CheckBoxField Sıralanırken Grup Üst Bilgileri Sıralanıyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Not
, veya alanları için CategoryID
veritabanı değerlerine NULL
sahip ürünleriniz varsa, bu değerler GridView'da varsayılan olarak boş dizeler olarak görünür; başka bir deyişle, değerleri olan NULL
ürünler için ayırıcı satırın metni Kategori: (kategoriden sonra bir ad yoktur: Kategori: İçecekler UnitPrice
SupplierID
gibi). Burada bir değerin görüntülenmesini istiyorsanız BoundFields NullDisplayText
özelliğini görüntülenmesini istediğiniz metne ayarlayabilir veya ayırıcı satır s Text
özelliğine atarken Render yöntemine currentValue
bir koşullu deyim ekleyebilirsiniz.
Özet
GridView, sıralama arabirimini özelleştirmek için birçok yerleşik seçenek içermez. Ancak, biraz düşük düzeyli kodla GridView'un denetim hiyerarşisini daha özelleştirilmiş bir arabirim oluşturmak için ayarlamak mümkündür. Bu öğreticide, ayrı grupları ve bu grupların sınırlarını daha kolay tanımlayan sıralanabilir gridview için sıralama grubu ayırıcı satırının nasıl ekleneceğini gördük. Özelleştirilmiş sıralama arabirimlerinin ek örnekleri için Scott Guthrie'ninA Few ASP.NET 2.0 GridView Sorting Tips and Tricks blog girdisine bakın.
Mutlu Programlama!
Yazar hakkında
Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışmaktadır. Son kitabı Sams Teach Yourself ASP.NET 24 Hours 2.0'dır. Adresine adresinden veya adresinden ulaşabileceğiniz http://ScottOnWriting.NETblogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.