Asi každý, kdo používá ovládací prvek „datagrid“, oceňuje volnost při navrhování šablon, kterou mu poskytuje takzvaný „TemplateColumn“. Ve sloupci můžeme například zobrazovat obrázek nebo zaškrtávací pole a podobně. Použití šablon má ale jednu nevýhodu – šablona je většinou uložena přímo v aspx stránce, a proto použití šablony v jiném projektu znamená její fyzické překopírování. Ukážeme si tedy vytvoření typového sloupce se šablonou pro zobrazení obrázku, který uvedenou nevýhodu odstraňuje.

I když se příklad týká vytvoření sloupce s obrázkem, princip vytváření typových sloupců je stále stejný, proto byste po přečtení článku měli být schopni sami vytvořit například sloupec, který zobrazí zaškrtávací pole (checkbox) nebo seznam (dropdownlist). U příkladu se předpokládá, že se obrázky nacházejí na disku a v databázi (XML souboru či jinde) jsou k uloženy cesty k obrázkům.

Šablony v ASP.NET

Libovolnou šablonu v ASP.NET si můžete zjednodušeně představit jako kolekci uživatelem definovaných ovládacích prvků, která je přidána do kolekce prvků nadřízeného ovládacího prvku (takzvaného kontejneru). V případě datově vázaných ovládacích prvků, jakým je právě datagrid, jsou všechny prvky ze šablony přidávány do kolekce prvků kontejneru opakovaně pro každý záznam v datovém zdroji. Je ale nutné si uvědomit, že kontejnerem je v datagridu pro každý záznam z datového zdroje jiná instance třídy DataGridItem. Každá šablona je typu ITemplate, což je rozhraní, které obsahuje jedinou metodu – InstantiateIn.

InstantiateIn(Control container);

Argument container je ovládací prvek, do jehož kolekce Controls budeme přidávat ovládací prvky z šablony.

Vytvoření typového sloupce s obrázkem

Ještě než začneme, můžete si stáhnout zdrojový kód příkladu i s testovací aplikací.

Ve VS.NET vytvoříme nový projekt typu Class Library a přidáme referenci na knihovnu System.Web.dll.

Nejdříve vytvoříme pomocnou třídu ImageTemplate, která bude reprezentovat šablonu, a proto musí implementovat rozhraní ITemplate:

internal class ImageTemplate : ITemplate
  {
  …
  }

S třídou ImageTemplate bude pracovat pouze náš typový sloupec, proto jsme jí přidělili modifikátor přístupu internal – třída je viditelná pouze v projektu, ve kterém byla deklarována.

Ve třídě ImageTemplate dále explicitně implementujeme metodu InstantiateIn z rozhraní ITemplate:

void ITemplate.InstantiateIn(Control container)
  {
    Image image = new Image();
    image.DataBinding += new EventHandler(setImageSrc);
    container.Controls.Add(image);
  }

V metodě vytvoříme instanci serverového ovládacího prvku Image, který bude použit pro vykreslení obrázku. Protože musíme zjistit z datového zdroje cestu k obrázku, přihlásíme si odběr události DataBinding, ke které dojde po volání metody DataBind datagridu. Na událost reaguje privátní metoda s názvem setImageSrc. Nakonec instanci prvku Image vložíme do kolekce Controls předaného kontejneru.

Třída ImageTemplate obsahuje jednu veřejnou vlastnost s názvem DataField, ve které je uložen název sloupce v datovém zdroji, jenž obsahuje cesty k obrázkům:

public string DataField
{
  get
  {
    return m_dataField;
  }
  set
  {
    m_dataField = value;
  }
}

Privátní metoda setImageSrc získá z datového zdroje cestu k obrázku a uloží ji do vlastnosti ImageUrl třídy Image.

private void setImageSrc(object sender, EventArgs e)
{
  Image image = (Image) sender;
  image.ImageUrl = String.Empty;
  DataGridItem item = (DataGridItem) image.NamingContainer;
  if (item.DataItem is DataRowView)
    image.ImageUrl = ((DataRowView)item.DataItem)[this.DataField].ToString();
  else if (item.DataItem is IDataRecord)
  {
    IDataRecord record = (IDataRecord)item.DataItem;
    image.ImageUrl = record.GetString(record.GetOrdinal(this.DataField));
  }
}

Metoda setImageSrc nejprve získá referenci na objekt z třídy Image, která událost vyvolala. Poté je vymazána aktuální hodnota vlastnosti ImageUrl. Z vlastnosti NamingContainer získáme po přetypování řádek datagridu, ve kterém bude obrázek zobrazen. Třída DataGridItem má vlastnost DataItem, ve které je uložen záznam z datového zdroje. V případě, že je datovým zdrojem datagridu instance třídy DataTable, vlastnost DataItem obsahuje odkaz na objekt z třídy DataRowView. Když je jako datový zdroj použit SqldataReader nebo OleDbDataReader, ve vlastnosti DataItem je odkaz na rozhraní IDataRecord.

Nyní musíme vytvořit třídu ImageColumn, která dědí z třídy TemplateColumn a zapouzdřuje vytváření šablony s obrázkem:

public class ImageColumn : TemplateColumn
{
  private ImageTemplate m_imgTemplate;
  public ImageColumn() : base()
  {
    m_imgTemplate = new ImageTemplate();
    this.ItemTemplate = m_imgTemplate;
    this.EditItemTemplate = m_imgTemplate;
}  
  public string DataField
  {
    get
    {
      return m_imgTemplate.DataField;
    }
    set
    {
      m_imgTemplate.DataField = value;
    }
  }
}

Jak vidíte, třída ImageColumn je poměrně jednoduchá. V konstruktoru vytvoříme instanci třídy ImageTemplate, která bude použita jako šablona při standardním zobrazení položky i při editaci položky. Jinými slovy, obrázek většinou editovat nechceme, takže jej pokaždé pouze zobrazíme. Ve třídě ImageColumn je také vlastnost DataField, která deleguje odpovědnost za nastavení (vydání) hodnoty atributu na třídu ImageTemplate.

Tím je náš nový sloupec hotov, o vše ostatní se již postará ASP.NET runtime. Knihovnu zkompilujte, vytvořte testovací ASP.NET aplikaci a přidejte referenci na knihovnu s novým sloupcem pro datagrid. Na stránce musíte nový sloupec zaregistrovat pomocí direktivy Register. Například takto:

<%@Register Assembly=“Interval.TemplateColumns“ Namespace=“Interval.TemplateColumns“ TagPrefix=“int“%>

Do datagridu můžete nový sloupec přidat tímto způsobem:

<int:ImageColumn HeaderText=“Obrázek2″ DataField=“Image1″>

ImageColumn je samozřejmě také možné vytvářet a přidávat do datagridu programově. ImageColumn můžete sami vylepšovat, bylo by asi vhodné minimálně přidat vlastnost, kterou určíte zarovnání obrázku ve sloupci. Také můžete například přidat další šablony pro záhlaví (HeaderTemplate) a zápatí (FooterTemplate).

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

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

Žádný příspěvek v diskuzi

Odpovědět