IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Génération automatique d'un gridview et ses templates

Cet article a pour but de vous présenter une technique pour générer dynamiquement un gridview avec un template sur mesure avec la méthode databind sur un formulaire à partir d'une structure de données. Soit une BD soit un fichier XML. ♪

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Dans de nombreuses situations, il est nécessaire de créer une gridview à la volée avec des données qui risquent de changer en cours de route. Cet article montre comment créer un gridview, y rajouter ses évènements de modification, maj et cancel. Et surtout la création de colonnes templates à la volée avec la méthode databind personnalisée selon le type de contrôle dans le template.

II. Avant de commencer

Vous démarrez idéalement d'une page vierge que nous appellerons Visualisation.Aspx. Placez dans cette page, un contrôle PlaceHolder qu'on nommera Placeholder1. Dans votre code HTML il devrait y avoir :

 
Sélectionnez
<asp:PlaceHolder ID=" PlaceHolder1" runat=" server"></asp:PlaceHolder>

Assurez-vous d'avoir une base de donnée SQL pour tester (NorthWind sera utilisée dans cet exemple). Ceci étant la base utilisée dans cet exemple. Maintenant que nous avons la base, nous pouvons nous concentrer sur le « code behind ».

III. Création de la gridview dynamiquement

Le gridview, comme n'importe quel autre contrôle du framework, peut être créé à l'aide d'un simple Dim Dans un premier temps, on va créer le contrôle, modifier ses propriétés et le lier à un datasource. Ensuite, vous allez voir, que les colonnes créées ne seront pas associées au gridview, mais au DataSource. Dans cet exemple, je me sers de la base exemple NorthWind sur SQL server 2000.

 
Sélectionnez
Dim cnn As New System.Data.SqlClient.SqlConnection ("Data Source=Serveur;Initial Catalog=Northwind;User ID=userId;password=MotDePasse")

Dim myDataset As New DataSet
Dim myDataset2 As New DataSet
Dim MyTable As DataTable = New DataTable
Dim MyDatarow As DataRow

Dim dtr As New SqlClient.SqlDataAdapter("SELECT Products.ProductID, Products.ProductName, Products.CategoryID Products ON Categories.CategoryID = Products.CategoryID", cnn)
Dim dtrCategory As New SqlClient.SqlDataAdapter("SELECT Categories.CategoryID, Categories.CategoryName FROM Categories ", cnn)

dtr.Fill(myDataset)
dtrCategory.Fill(myDataset2)

Dim GrdDynamic As New GridView

GrdDynamic.DataSource = myDataset.Tables(0)
GrdDynamic.DataBind()
PlaceHolder1.Controls.Add(GrdDynamic)

OK, le résultat ressemble à ceci :

Image non disponible
Figure 1

Simple non? Mais, comment modifier les lignes ? Et également avoir plusieurs choix pour la catégorie ? C'est là que la création dynamique des templates est obligatoire.

IV. Ajout d'une classe Itemplate

Un template, pour vulgariser, est une description particulière d'un rendu au moment de l'exécution. Il détermine l'aspect « layout » et la partie liée « binding » d'un contrôle. Parce que nous ne savons pas, a priori, quels champs seront dans notre datagrid, nous devons utiliser des templates dynamiques. Ceci se fait avec l'implémentation de Itemplate. Nous devons générer le ItemTemplate et le EditItemTemplate dynamiquement pour chacun des champs.

ITemplate a une méthode InstantiateIn que je décrirai plus bas. La classe GridViewTemplate qui implémente cette interface, expose n'importe quelle propriété de la gridview comme la sienne, alors le « layout » par défaut est surpassé. Pour pouvoir réutiliser la classe dans d'autres situations, j'ai décidé de l'extentier dans une classe à part.

Voici la structure générale de la classe GridViewTemplate :

 
Sélectionnez
Public Class GridViewTemplate
    Implements ITemplate

    Dim _templateType As ListItemType
    Dim _columnName As String
    Dim _TypeControl As String = "TextBox"
    Dim _Dts As DataSet

Public Sub New(ByVal Type As ListItemType, ByVal colname As String, ByVal TypeControl As String)

        _templateType = Type
        _columnName = colname
        _TypeControl = TypeControl

End Sub

Public Sub InstantiateIn
End Sub

Sub DataBinding (ByVal sender As Object, ByVal e As EventArgs)
End Sub

_templateType est le type de template (Item, Edit, etc.), _columnName le nom de la colonne, et _TypeControl le type de contrôle qui sera rendu dans notre template. Vous pouvez avoir plusieurs constructeurs, moi j'ai choisi d'en avoir deux. Ceci pour maîtriser si un template contient une liste de valeurs passée comme un dataset que je peux associer à un listbox ou un autre contrôle.

 
Sélectionnez
Public Sub New(ByVal Type As ListItemType, ByVal colname As String, ByVal TypeControl As String)

        _templateType = Type
        _columnName = colname
        _TypeControl = TypeControl

End Sub

Public Sub New(ByVal Type As ListItemType, ByVal colname As String, ByVal TypeControl As String, ByVal dts As DataSet)

        _templateType = Type
        _columnName = colname
        _TypeControl = TypeControl
        _Dts = dts

End Sub

La méthode InstantiateIn est la première partie de ma classe. Cette méthode s'assure que le type de template est créé par rapport à son contrôle prédéfini. Je vais dans cet exemple m'occuper type ItemTemplate et de EditTemplate. Il y en a d'autres : HeaderTemplate etc. Regardons mon exemple :

 
Sélectionnez
Select Case _templateType

    Case ListItemType.Item

        Select Case UCase (_TypeControl)
            Case "BUTTON"
                Dim tb1 As Button = New Button()
                AddHandler tb1.Click, AddressOf tb1_EditClik
                tb1.CommandName = "EDIT"
                container.Controls.Add(tb1)
            Case "LABEL"
                Dim tb1 As Label = New Label()
                tb1.BorderStyle = BorderStyle.None
                AddHandler tb1.DataBinding, AddressOf tb1_DataBindingLabel
                container.Controls.Add(tb1)
            Case "LISTBOX"
                Dim mylistbox As DropDownList = New DropDownList
                mylistbox.DataSource = _Dts.Tables(0)
                AddHandler mylistbox.DataBinding, AddressOf tb1_DataBindingListBox
                mylistbox.DataTextField = _columnName
                mylistbox.DataValueField = _columnName2
                mylistbox.ID = ("lstDynamique")
                mylistbox.Enabled = False
                container.Controls.Add(mylistbox)
                End Select
        End Select

Un point important à ne pas manquer c'est que j'initialise la propriété CommandName de mon bouton à « EDIT ». Ceci aura pour effet de démarrer la méthode associée au gridview.

L'autre point important c'est que j'ai rajouté des AddHandlers. C'est là que j'effectue mon databinding. Remarquez bien la partie DataBinder.Eval.

Pour l'étiquette :

 
Sélectionnez
Sub tb1_DataBindingLabel(ByVal sender As Object, ByVal e As EventArgs)

        Dim lbldata As Label = CType(sender, Label)
        Dim container As GridViewRow = CType(lbldata.NamingContainer, GridViewRow)
        Dim dataValue As Object = DataBinder.Eval(container.DataItem, _columnName)

        If Not IsNothing(dataValue) Then
            lbldata.Text = WrappableText(dataValue.ToString)
        End If

    End Sub

Pour le listBox :

 
Sélectionnez
Sub tb1_DataBindingListBox(ByVal sender As Object, ByVal e As EventArgs)

        Dim lst As DropDownList = CType(sender, DropDownList)
        Dim container As GridViewRow = CType(lst.NamingContainer, GridViewRow)
        Dim dataValue As Object = DataBinder.Eval(container.DataItem, _columnName)

        If Not IsNothing(dataValue) Then
            lst.SelectedValue = dataValue.ToString
        End If

    End Sub

Aucune différence !!!!!!!!!!!!!!! OK cela c'est pour le ITEMTEMPLATE, celui du EDIT est un peut différent. Regardez :

 
Sélectionnez
Case ListItemType.EditItem
    
    Select Case UCase (_TypeControl)
        Case "BUTTON"
            Dim tb1 As Button = New Button()
            tb1.Visible = True
            tb1.CommandName = "Update"
            If HttpContext.Current.Session ("InsertFlag") = 1 Then
                tb1.Text = "Ajouter"
            Else
                tb1.Text = "MAJ"
            End If
            tb1.OnClientClick = "return confirm('Êtes-vous sûr de MAJ ?')"
            container.Controls.Add(tb1)
            Dim tb2 As Button = New Button()
            tb2.CommandName = "Cancel"
            container.Controls.Add(tb2)
        Case "LABEL"
            Dim tb1 As Label = New Label()
            tb1.BorderStyle = BorderStyle.None
            AddHandler tb1.DataBinding, AddressOf tb1_DataBindingLabel
            tb1.Visible = True
            container.Controls.Add(tb1)
        Case "LISTBOX"
            Dim mylistbox As DropDownList = New DropDownList
            mylistbox.DataSource = _Dts.Tables(0)
            AddHandler mylistbox.DataBinding, AddressOf tb1_DataBindingListBox
            mylistbox.DataTextField = _columnName
            mylistbox.DataValueField = _ColumnName2
            mylistbox.ID = ("lstDynamique")
            mylistbox.Enabled = True
            container.Controls.Add(mylistbox)
        Case "TEXTBOX"
            Dim tb1 As TextBox = New TextBox()
            tb1.BorderStyle = BorderStyle.None
            AddHandler tb1.DataBinding, AddressOf tb1_DataBindingTextBox
            tb1.Columns = 4
            tb1.Visible = True
            container.Controls.Add(tb1)
    End Select
End Select

J'ai deux boutons au lieu d'un : Update et Cancel. Les deux sont associés aux CommandName Update et Cancel. Le Listbox est actif et il y a un Textbox. De plus, remarquez que ce sont les mêmes AddHandlers… C'est parce que le databinding est bidirectionnel. C'est la même méthode qui gère la récupération et la sauvegarde !

OK l'implémentation de l'ITemplate est terminée. Allons voir comment s'en servir.

V. Utilisation de ITemplate

Vous avez créé la gridview et créé la classe qui implémente ITemplate. Maintenant on va voir comment s'en servir !

En premier lieu il faut modeler la table et les colonnes qui vont structurer notre gridview.

 
Sélectionnez
Dim MyTable As DataTable = New DataTable
Dim MyDatarow As DataRow

Dim dcol As Data.DataColumn = New Data.DataColumn("ProductId", GetType(System.Int32))
MyTable.Columns.Add(dcol)

dcol = New Data.DataColumn("ProductName", GetType(System.String))
MyTable.Columns.Add(dcol)

dcol = New Data.DataColumn("CategoryID", GetType (System.Int32))
MyTable.Columns.Add(dcol)

Ensuite, y rajouter les lignes :

 
Sélectionnez
For Each MyDatarow In myDataset.Tables(0).Rows
    Dim drow As Data.DataRow = MyTable.NewRow
            
    drow("ProductId") = MyDatarow("ProductId")
    drow("ProductName") = MyDatarow("ProductName")
    drow("CategoryID") = MyDatarow("CategoryID")
    MyTable.Rows.Add(drow)
Next

Notre table est maintenant modélisée. Maintenant, attardons-nous au gridview. Premièrement, il faut lui dire que les colonnes ne seront pas générées automatiquement . Et ensuite, lui rajouter les méthodes Update, Edit et Cancel:

 
Sélectionnez
GrdDynamic.AutoGenerateColumns = False

AddHandler GrdDynamic.RowEditing, AddressOf GrdDynamic_RowEditing
AddHandler GrdDynamic.RowUpdated, AddressOf GrdDynamic_RowUpdated
AddHandler GrdDynamic.RowCancelingEdit, AddressOf GrdDynamic_RowCancelingEdit

OK tout est prêt pour la magie… Il faut rajouter dans notre table (et ensuite dans notre gridview) les champs Template. C'est assez facile. Commençons par les boutons de commande :

 
Sélectionnez
Dim cmdfield As TemplateField = New TemplateField

cmdfield.ItemTemplate = New GridViewTemplate(ListItemType.Item, "...", "button")
cmdfield.EditItemTemplate = New GridViewTemplate(ListItemType.EditItem, "...", "button")

GrdDynamic.Columns.Add (cmdfield)

Et maintenant pour chaque colonne de la table :

 
Sélectionnez
For Each col As DataColumn In MyTable.Columns

    Dim bfield As TemplateField = New TemplateField
    
    If col.ColumnName = "CategoryID" Then
        Dim ColumnName2 As String = "CategoryName"
        bfield.ItemTemplate = New GridViewTemplate(ListItemType.Item, col.ColumnName, ColumnName2, "ListBox", myDataset2)
        bfield.EditItemTemplate = New GridViewTemplate(ListItemType.EditItem, col.ColumnName, ColumnName2, "ListBox", myDataset2)
    ElseIf col.ColumnName = "ProductId" Then
        bfield.ItemTemplate = New GridViewTemplate(ListItemType.Item, col.ColumnName, "Label")
    ElseIf col.ColumnName = "ProductName" Then
        bfield.ItemTemplate = New GridViewTemplate(ListItemType.Item, col.ColumnName, "Label")
        bfield.EditItemTemplate = New GridViewTemplate(ListItemType.EditItem, col.ColumnName, "textbox")
    End If
    
    GrdDynamic.Columns.Add(bfield)

Next

Et finalement je lie le tout au Gridview

 
Sélectionnez
GrdDynamic.DataSource = myDataset. Tables (0)
GrdDynamic.DataBind()
PlaceHolder1.Controls.Add(GrdDynamic)

Il ne faut surtout pas oublier de créer les méthodes GrdDynamic_RowUpdated, GrdDynamic_RowEdited et GrdDynamic_RowCancelingEdit. Dans la méthode GrdDynamic_RowEditing ne pas oublier de modifier l'index et d'effectuer le databind du gridview :

 
Sélectionnez
Sub GrdDynamic_RowEditing (ByVal sender As Object, ByVal e As GridViewEditEventArgs)

CType(sender, GridView).EditIndex = e.NewEditIndex
CType(sender, GridView).DataBind()
End Sub

Vous devriez maintenant avoir ceci :

Image non disponible

VI. Conclusion

La création d'un gridview avec ses évènements traditionnels et des templates de manière dynamique peut s'avérer parfois très utile. J'ai, dans cet article essayé de vous démontrer de manière simple comment le faire. J'ai volontairement mis de côté des bouts qui auraient amené de la confusion. L'essentiel est pourtant la. Vous pouvez jouez du côté du datasource, des évènements et rajouter n'importe quel contrôle dans les templates.

Amusez-vous bien !

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Les sources présentés sur cette pages sont libre de droits, et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright Martin Tremblay . Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérets.