Hayadi's Blog

vendredi, décembre 23, 2005

construire dynamiquement ses colonnes de DataGrid

Cette astuce vous montre comment créer dynamiquement des colonnes complexes dans des DataGrid .
Il se peut que de temps en temps, vous deviez créer dynamiquement des colonnes dans un DataGrid. De plus, il se peut que cette colonne soit un peu "complexe", c'est-à-dire contenant des contrôles différents suivant un context particulier.
Par exemple, imaginons que si la variable Session "Context" est égale à "Admin", on ajoute une colonne avec un Hyperlink, sinon un label.
Dans l'un des évènements d'initialisation de notre page, on va donc créer dynamiquement cette colonne. Suivant ce que vous voulez faire, cela peut être dans l'évènement Page_Init, Page_AttachControls ou tout simplement Page_Load (ne surtout pas gérer la IsPostBack dans ce cas).
On aura donc dans cet évènement le code suivant :

TemplateColumn column = new TemplateColumn();
column.ItemTemplate = new MyTemplate(Session["Context"].ToString());
DataGrid1.Columns.Add(column);

On appel le constructeur de notre nouvelle classe MyTemplate qui attend, comme on va le voir, un string définissant son aspect (ok, je sais, il faudrait déclarer une énumération pour bien typer le constructeur plutôt qu'un string quelconque, mais j'ai pas le temps là!!!).
Donc on ajoute une nouvelle "TemplateColumn" colonne. Vous aurez remarqué que l'on a défini le ItemTemplate comme MyTemplate. Cette dernière classe doit impérativement implémenter l'interface ITemplate qui défini la méthode InstantiateIn.
C'est cette méthode, InstantiateIn qui sera appelée lors de la construction de la colonne. C'est dans cette méthode que l'on créera nos contrôles particuliers :

private class MyTemplate : ITemplate
{ bool m_Admin;
public MyTemplate(string sAdmin)
{ if (sAdmin == "Admin")
m_Admin = true;
}
#region ITemplate Members
public void InstantiateIn(Control container)
{ Control ctrl = null;
if (m_Admin)
{
ctrl = new HyperLink();
}
else
{
ctrl = new Label();
}
ctrl.ID = "ctrl";
container.Controls.Add(ctrl);
}
#endregion
}


Maintenant pour "remplir" ma colonne, je peux réagir dans l'évènement ItemDataBound :

Control ctrl = e.Item.FindControl("ctrl");
if (ctrl is HyperLink)
{
((HyperLink) ctrl).Text = ((Personne) e.Item.DataItem).Nom;
((HyperLink) ctrl).NavigateUrl = "editPersonne.aspx?ID=" + ((Personne) e.Item.DataItem).ID.ToString();
}
else
{
((Label) ctrl).Text = ((Personne) e.Item.DataItem).Nom;
}

Et Voila ?