Gyakran van szükség arra, hogy a ListView vezérlőben megjelenő rekordokat valamilyen szempont szerint csoportosítsuk. A ListView támogat is csoportosítást, azonban ez a funkció csak arra jó (?), hogy megadott számú elemet tegyünk egy csoportba, azt sajnos nem támogatja, hogy megadott érték szerint csoportosítsuk a rekordokat. Persze hagyományos módon meg lehet oldani ezt is.
Ezt tudja a ListView csoportosítás címén: a LayoutTemplate-et GroupTemplate-ekkel tölti fel, közéjük pedig GroupSeparatorTemplate-et rak. Minden egyes GroupTemplate-be a GroupItemCount tulajdonságban megadott számú ItemTemplate kerül. Ha egy csoportban (tipikusan az utolsóban) nincs elég elem, akkor azokat a helyeket EmptyItemTemplate-tel tölti fel. Ez szerintem arra van kitalálva, hogy az ember táblázatba rendezze a rekordokat, ott számít ugyanis, hogy minden sorba ugyanannyi elem kerüljön.
De mi van akkor, ha nem darabszám, hanem érték szerint akarjuk csoportosítani a sorokat? Ez esetben kénytelenek leszünk lemondani a beépített csoportosításról és az ASP.NET 1.0-ban megszokott módon megoldani a feladatot.
Először is rendezzük a csoportképző mező szerint az adatokat, például ha a Northwind adatbázis Customer táblájának sorait ország szerint csoportosítva, azon belül pedig cégnév szerint rendezve akarjuk megjeleníteni, akkor így:
SELECT CompanyName, ContactName, Country FROM Customers ORDER BY Country, CompanyName
Az eredmény (részlete):
Már csak annyi dolgunk maradt, hogy a Country mezőváltozásai esetén kell megjelenítenünk egy csoportfejlécet. A trükk az, hogy nem használjuk a beépített csoportosítást, hanem (például) egy sima h2 elemre rácuppanunk szerver oldalon (runat=server), majd a Visible tulajdonságát egy szerver oldali metódussal állítjuk be:
<asp:ListView runat="server" DataSourceID="sdsCustomers">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</LayoutTemplate>
<ItemTemplate>
<h2 runat="server" visible='<%# IsGroupHeaderVisible( Eval( "Country" ) ) %>'>
<%# Eval( "Country" ) %>
</h2>
<%# Eval( "CompanyName" ) %>
-
<%# Eval( "ContactName" ) %>
</ItemTemplate>
<ItemSeparatorTemplate>
<br />
</ItemSeparatorTemplate>
</asp:ListView>
Ezek után a code behindban kell egy privát mező az előző érték tárolására és a függvény, ami az aktuális értéket összehasonlítja az előzővel:
private string _lastValue;
protected bool IsGroupHeaderVisible( object value )
{
string currentValue = value.ToString();
if( currentValue.Equals( this._lastValue, StringComparison.OrdinalIgnoreCase ) )
{
return false;
}
else
{
this._lastValue = currentValue;
return true;
}
}
Az eredmény pedig:
Látható, hogy az egész azon alapul, hogy a rekordok jó sorrendben legyenek, de egyébként teljesen a mi kezünkben van az irányítás, olyan szempont szerint csoportosítunk, ahogy kedvünk tartja.
A cikkhez tartozó forráskód letölthető itt.