Třídění v ovládacím prvku DataGrid

18. března 2004

Máte dlouhý výpis různých položek a chcete umožnit uživateli setřídit ho podle jednotlivých sloupců, ať už vzestupně nebo sestupně? V tomto článku vám předvedu, že to jde poměrně snadno, a to i bez velkého programování. Samozřejmě za pomoci ovládacího prvku DataGrid.

Co je tedy potřeba provést pro spuštění třídění? V zásadě pouze dva jednoduché úkony:

  • povolit třídění vlastností AllowSorting
  • implementovat metodu ošetřující událost OnSortCommand

Začneme podobně jako v předchozím článku, ale nyní místo stránkování nastavíme na true vlastnost AllowSorting a tím povolíme vlastní řazení:

<%@ Page language=“c#“ Codebehind=“priklad2.aspx.cs“ AutoEventWireup=“false“ Inherits=“DATAGRID1.priklad2″ %>
<!DOCTYPE HTML PUBLIC „-//W3C//DTD HTML 4.0 Transitional//EN“ >
<HTML>
 <HEAD>
  <title>priklad2</title>
  <meta name=“GENERATOR“ Content=“Microsoft Visual Studio .NET 7.1″>
  <meta name=“CODE_LANGUAGE“ Content=“C#“>
  <meta name=“vs_defaultClientScript“ content=“JavaScript“>
  <meta name=“vs_targetSchema“ content=“http://schemas.microsoft.com/intellisense/ie5″>
 </HEAD>
 <body>
  <form id=“Form1″ method=“post“ runat=“server“>
   <asp:DataGrid id=“DG“ runat=“server“ AllowSorting=“True“></asp:DataGrid>
  </form>
 </body>
</HTML>

V dalším kroku provedeme implementaci metody zajištující vlastní třídení:

private void trideni(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
SqlConnection conn1=new SqlConnection(ConfigurationSettings.AppSettings[„conn_DB“]);
conn1.Open();
string SQL_Dotaz;
SQL_Dotaz=“SELECT ProductID,ProductName,UnitPrice FROM Products“;
SqlDataAdapter cmd1=new SqlDataAdapter(SQL_Dotaz,conn1);
DataSet ds=new DataSet();
cmd1.Fill(ds);
cmd1.Dispose();
// pristup do db uz nepotrebujeme zavreme je tedy
conn1.Close();
conn1 = null;
DataView pohled=new DataView(ds.Tables[0]);
pohled.Sort = e.SortExpression.ToString();
DG.DataSource=pohled;
DG.DataBind();
}

Pokud jste četli předchozí článek, jistě vás napadne, proč, když jsem minule použil pro nastavení stránky vlastnost DataGridu, to neudělám i nyní. Odpověď je jednoduchá. DataGrid totiž nemá možnosti, pomocí nichž by bylo možno přímo setřídit data. K tomuto účelu je nutno použít objekt DataView, který tuto možnost má, a výsledek jeho činnosti pak „podat“ DataGridu jako zdroj dat. Více o použití a možnostech objektu DataView si můžete přečíst přímo v MSDN. Pokud však použitý datový zdroj umožňuje třídění, lze samozřejmě použít třídění poskytované přímo datovým zdrojem. (Abych vyvedl z omylu všechny, kteří si myslí, že datový zdroj musí automaticky být databáze, dovolím si upozornit, že jako datový zdroj lze použít třeba i výpis obsahu adresáře.)

Chcete-li se přesvědčit o funkčnosti výše uvedeného, můžete se jednak podívat na výsledek činnosti příkladu on-line, druhak si stáhnout zdrojový kód pro pozdější výzkum.

Takto jednoduché to je ovšem pouze tehdy, pokud vlastnost AutoGenerateColumns nastavena na true, neboli je v defaultním (základním) stavu. Pokud však nechcete třídit podle všech sloupců nebo chcete zobrazované sloupce upravit, bude podoba definice DataGridu poněkud složitější. Je potřeba vytvořit vlastní sloupce. Pro nás jsou nyní důležité vlastnosti DataField, která mapuje sloupec na datový zdroj, a HeaderText, která určuje obsah záhlaví sloupce. Tou nejdůležitější je v tomto článku ovšem vlastnost SortExpression, která určuje, jakým způsobem budou data setříděna. (Více informací o sloupcích v DataGridu získáte v MSDN.)

<asp:DataGrid id=“DG“ runat=“server“ AllowSorting=“True“ AutoGenerateColumns=“False“>
<Columns>
<asp:BoundColumn DataField=“ProductID“ SortExpression=“ProductID“ HeaderText=“Číslo“></asp:BoundColumn>
<asp:BoundColumn DataField=“ProductName“ SortExpression=“ProductName DESC“ HeaderText=“Název“></asp:BoundColumn>
<asp:BoundColumn DataField=“UnitPrice“ HeaderText=“Cena“></asp:BoundColumn>
</Columns>
</asp:DataGrid>

Všimněte si, že jsem u sloupce s hlavičkou „Cena“ neuvedl vlastnost SortExpression – podle tohoto sloupce nebude mít uživatel možnost třídit.

Problémy ale nastanou, pokud potřebujeme řadit jeden sloupec vzestupně i sestupně. Zde bude potřeba trochu více programování, i když ho nebude nijak moc. Pro větší přehlednost kódu si vytvoříme funkci, která bude jako parametr vyžadovat výraz, podle něhož se má provést třídění. Tato funkce na základě zadaného parametru provede setřídění dat a naplnění DataGridu:

void setrid(string triditpodle)
{
SqlConnection conn1=new SqlConnection(ConfigurationSettings.AppSettings[„conn_DB“]);
conn1.Open();
string SQL_Dotaz;
SQL_Dotaz=“SELECT ProductID,ProductName,UnitPrice FROM Products“;
SqlDataAdapter cmd1=new SqlDataAdapter(SQL_Dotaz,conn1);
DataSet ds=new DataSet();
cmd1.Fill(ds);
cmd1.Dispose();
// pristup do db uz nepotrebujeme zavreme je tedy
conn1.Close();
conn1 = null;
DataView pohled=new DataView(ds.Tables[0]);
pohled.Sort = triditpodle;
DG.DataSource=pohled;
DG.DataBind();
}

Nejobtížnější částí je zjišťování, podle čeho třídit, a zabezpečení požadovaného chování, tedy toho, že po druhém kliknutí na stejný odkaz budou data setříděna opačným směrem:

private void trideni(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
string [] tridici_vyraz;
string smer_trideni;
tridici_vyraz= e.SortExpression.Split(new char[]{‚ ‚});
if (tridici_vyraz.Length>1)
{
smer_trideni=tridici_vyraz[1];
if (smer_trideni.ToUpper()==“ASC“)
smer_trideni=“Desc“;
else
smer_trideni=“Asc“;
}
else
smer_trideni=“Desc“;
for(int i=0;i < DG.Columns.Count;i++)
if (DG.Columns[i].SortExpression.IndexOf(e.SortExpression)==0)
DG.Columns[i].SortExpression=tridici_vyraz[0]+“ „+smer_trideni;
setrid(tridici_vyraz[0]+“ „+smer_trideni);
}

Výsledek činnosti skriptu můžete opět vidět on-line v druhém příkladu a k dispozici je vám i rozšířený zdrojový kód.

Až doposud jsme v příkladech prováděli řazení pomocí objektu DataView, ale co použít pro řazení prostředek, který bude zcela určitě rychlejší a přesnější? V dalším příkladu vám předvedu, jak pro řazení použít přímo datový zdroj (v tomto případě je to SQL server). Změna, kterou provedeme, se bude týkat pouze funkce setrid, kde trochu pozměníme způsob načítání dat z datové zdroje:

void setrid(string triditpodle)
{
SqlConnection conn1=new SqlConnection(ConfigurationSettings.AppSettings[„conn_DB“]);
conn1.Open();
string SQL_Dotaz;
SQL_Dotaz=“SELECT ProductID,ProductName,UnitPrice FROM Products order by „+triditpodle;
SqlDataAdapter cmd1=new SqlDataAdapter(SQL_Dotaz,conn1);
DataSet ds=new DataSet();
cmd1.Fill(ds);
cmd1.Dispose();
// pristup do db uz nepotrebujeme zavreme je tedy
conn1.Close();
conn1 = null;
DG.DataSource=ds;
DG.DataBind();
}

Ukázka k tomuto příkladu je z hlediska uživatele identická s ukázkou k předchozí verzi skriptu, můžete si ovšem stáhnout kompletní zdrojový kód a trochu si s ním pohrát, například přidat do záhlaví každého tříditelného sloupce šipku, ukazující aktuální stav setřídění…

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek stranky
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *