Zrovna předevčírem jsem měl v plánu napsat tenhle článek, ráno jsem si napsal ukázkovou třídu, kterou najdete níže, a pak šel do práce. Připravoval jsem dva celkem důležité stagingy a nakonec ještě ta Havana Party. No, a když jsem se vrátil z nákupu, zastihl jsem přímý přenos ze spouštění La Trine. A bylo po článku. Teda jen dočasně, protože i včera jsem měl nějakou snahu, tak jsem napsal první půlku článku.
Někdy před rokem jsem publikoval ukázku, jak si vytvořit vlastní kontrol s Layout Template. Před pár týdny zase pomocníka na vyhledávání komponent ve stránce i mimo jmenný kontejner. To jsou takoví pomocníci, kteří mi usnadňují tvorbu serverových ovládacích prvků. A dneska si ukážeme jejich dalšího bratříčka – generický kontejner.
Kontejner
Kontenery se používají u šablonovaných prvků svázaných s daty. Slouží jako držitel dat pro konkrétní instanci šablony. Jistě jste se setkali s Evalováním, když jste prováděli databinding. Problém je v tom, že s sebou přináší značnou režii spojenou s boxingem. Výhodnější je používat plně typový kontejner. Zvýšíte tím nejen výkon stránky, ale i zístkáte vyšší komfort v podobě Intellisense v šabloně.
Já jako základ takových kontejnerů používám generický kontejner, který má následující rozhraní.
public interface IGenericContainer<T> : INamingContainer {
T DataItem { get; }
}
Toto rozhraní pak implementuju následovně:
public class GenericContainer<T> : Control, IGenericContainer<T> {
public GenericContainer<T>(T dataItem) {
DataItem = dataItem;
}
public T DataItem { get; priváte set; }
}
Dalším vhodným kontejnerem je prázdný kontejner:
public class EmptyContainer : Control, INamingContainer {
}
S těmito kontejnery se dá pokrýt obrovské množství potřeb. Jak je využít v praxi si ukážeme v následující části.
Generický repeater
Nyní vezmu kostičky naší stavebnice a postavím z nich základ pro vypisovače silně typových dat.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Rarous.Web.UI {
[ParseChildren(true)]
public abstract class GenericRepeaterBase<T> : CompositeControl, ILayoutTemplateable {
protected bool IsBound { get; set; }
public IEnumerable<T> DataItem { get; set; }
public abstract ITemplate ItemTemplate { get; set; }
public abstract ITemplate AlternatingItemTemplate { get; set; }
[DefaultValue(typeof(ITemplate), "")]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(INamingContainer))]
[TemplateInstance(TemplateInstance.Multiple)]
public ITemplate SeparatorTemplate { get; set; }
#region ILayoutTemplateable Members
[PersistenceMode(PersistenceMode.Attribute)]
public string LayoutContainerId { get; set; }
[DefaultValue(typeof(ITemplate), "")]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(INamingContainer))]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate LayoutTemplate { get; set; }
#endregion
#region CompositeControl Members
protected override void CreateChildControls() {
Control container = TemplatingHelper.CreateLayoutContainer(this, this);
bool alternate = false;
foreach (T item in DataItem) {
ITemplate template = alternate ? AlternatingItemTemplate ?? ItemTemplate : ItemTemplate;
TemplatingHelper.Instantiate(new GenericContainer<T>(item), template, container);
TemplatingHelper.Instantiate(new EmptyContainer(), SeparatorTemplate, container);
alternate = !alternate;
}
}
public override void DataBind() {
base.DataBind();
IsBound = true;
}
protected override void OnInit(EventArgs e) {
EnableViewState = false;
base.OnInit(e);
}
protected override void OnPreRender(EventArgs e) {
if (IsBound == false) {
DataBind();
}
base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer) {
base.RenderContents(writer);
}
#endregion
}
}
Na takovémto základě se dá stavět už slušná řada konkrétních ovládacích prvků, kde už jen doplníme šablonový typ a můžeme přidat další vlastnosti dle potřeby.
V ukázce si můžete povšimnout, že jako typ kontejneru šablony uvádím
pouze rozhraní. Dělám to kvůli zpřehlednění IntelliSense. Když pak
používám výraz pro svázání s daty v šabloně, dostanu pouze vlastnosti
a metody kontejneru, které jsou definovány rozhraním, nikoli spoustu
zbytečných vlastností a metod, které sebou nese třída Control
ze které musí být kontejner poděděný.
Doufám, že se bude hodit a pokud najdete nějakou chybu, neváhejte a reportujte :)











Komentáře
Zatím bez komentáře. Buď první!
Místo pro tvůj názor