Detailsview entierement dynamique par du code behind en asp.net 2.0 VB

Signaler
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007
-
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007
-
Bonjour je plante depuis 15 jours sans  trouver la solution !
mon problème....
je vais choisir dans un dropdownlist une base utilisateur sur sqlserv2005 (entierement en recursif + enregistrements a champs variables via xml)

j'affiche les tables dans un grid (General)

lorsque je selectionne une table les enregistrements s'affichent dans un autre grid (Maitre)
lorsque je selectionne un enregistrement il s'affiche dans un detailview (Detail) pour modification.

resumé le detailview (Detail) ne peut savoir par avance le nom des champs et leur type.

j'arrive a afficher jusqu'au detailview mais lorsque je clique sur "edit" j'ai un message d'erreur sur l'index
Specified argument was out of the range of valid values.
Parameter name: index

je pense ne pas savoir bien construire un detailsview dynamique en code behind (vb)

precision : je sauvegarde l'index lu dans Maitre dans une variable session et j'ai aussi essayé de premplacer "([id] = @id) " par ([id] =" &  session("monID") & ")"

j'affiche a l'ecran ce que je construis dans mon code behind

SelectCommand---> SELECT * FROM T_Famille WHERE ([id] = @id)
InsertCommand---> INSERT INTO T_Famille (id_rayon, nom_famille_1, nom_famille_2, nom_famille_3, position, actif) VALUES (@id_rayon, @nom_famille_1, @nom_famille_2, @nom_famille_3, @position, @actif)
UpdateCommand---> UPDATE T_Famille SET id_rayon= @id_rayon, nom_famille_1= @nom_famille_1, nom_famille_2= @nom_famille_2, nom_famille_3= @nom_famille_3, position= @position, actif= @actif @id_rayon, @nom_famille_1, @nom_famille_2, @nom_famille_3, @position, @actif WHERE ([id] = @id)
SelectCommand---> SELECT * FROM T_Famille WHERE ([id] = @id)
InsertCommand---> INSERT INTO T_Famille (id_rayon, nom_famille_1, nom_famille_2, nom_famille_3, position, actif) VALUES (@id_rayon, @nom_famille_1, @nom_famille_2, @nom_famille_3, @position, @actif)
InsertParameters---> name =id
InsertParameters---> name =id_rayon
InsertParameters---> name =nom_famille_1
InsertParameters---> name =nom_famille_2
InsertParameters---> name =nom_famille_3
InsertParameters---> name =position
InsertParameters---> name =actif
UpdateParameters---> name =id_rayon
UpdateParameters---> name =nom_famille_1
UpdateParameters---> name =nom_famille_2
UpdateParameters---> name =nom_famille_3
UpdateParameters---> name =position
UpdateParameters---> name =actif

merci de m'aider

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu

12 réponses

Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Bonsoir :-)

Je ne comprend pas vraiment le problème, donc j'essaye de résumer : tu affiche une table que tu connais pas à l'écran avec un gridview ayant autogenerateColumn à true je suppose, ensuite quand tu click sur une row tu essaye d'afficher le détails de celle ci pour pouvoir la modifier ?

Tu arrives à afficher les détails mais quand tu cliques sur Edit ca plante ?

Je pense avoir une petite idée du pourquoi ... :-)

Tu Binds ton DetailsView sur l'evenement SelectedIndexChanged de ton GridView ?

ce qu'il faut savoir c'est que pour que les evenement soient lancé il faut que le controle soient présent dans l'arbre avant le page_load (c'est pour cette raison qu'il faut rajouté les controles dynamique dans le page_init) or dans ton cas le detailsView n'existe pas encore vu que le binding se fait sur l'evenement selectedindexchanged qui vient aprés le page_load ...

la solution consisterais de binder le détailsview avant, lorsque tu es sur le selectedindexchanged tu sauvegardes l'index dans la session et tu bind le gridview le plus tot possible.

J'ai l'impression de m'etre entravé quelque part et donc d'avoir une conclusion fausse, tu utilises un sqldatasource ?

<hr />Cyril - MVS - MCP
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

cher Cyril.
merci pour ta reponse qui apporte peut etre la solution a mon probleme je vais tester immediatement.
cela dit ce que j'affiche n'est jamais connu a l'avance : je dois tout construire
1) je cherche sur le reseau des instances sqlserver
2)je me connecte a celle choisie
3)je demande l'affichage des tables utilisateurs s'y trouvant
4)je selectionne une table
5)je l'affiche dans un grid(dit maitre)
6)quand je selectionne un enregistrement (row c'est ca ?) je l'affiche dans un detailview pour modification (ajout & suppression possible si la recursivite le permet).
7)les enreg de niveau le plus bas sont a champs variables (en fonction du groupe auxquels ils appartiennent) via un masque xml. Pour eux je n'ai pas encore la solution, mais chaque chose en son temps.

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

pour mieux repondre a tes questions :  oui je Binds mon DetailsView sur l'evenement SelectedIndexChanged de ton GridView ?
mais avant, je dois recuperer les noms des colonnes
//SelectStatement =
"SELECT COLUMN_NAME, data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" & Session(
"fic") &
"'"//
ensuite j'essaye de creer en dynamique les valeurs que j'ai vu dans les exemples en "declaratif" en recréant tous les paramettres par exemple :
Details_View.Fields.Clear()

For
Each Row
In fichierDS.Tables(Session(
"fic")).Rows
      
Dim bFld
As BoundField =
Nothing
      bFld =
New BoundField()
      bFld.DataField = Row.Item(0)
      bFld.HeaderText = Row.Item(0)
      
If bFld.DataField =
"id"
Then
      bFld.ReadOnly =
"True"
      End
If
Details_View.Fields.Add(bFld)

ensuite je cree les commandes
Details.SelectCommand =
""
Details.ConnectionString =
""
Details.InsertCommand =
""
Details.UpdateCommand =
""

que j'affiche à l'ecran pour verifier qu'elles correspondent bien a celles que je trouve dans les exemples "en declaratif"
ensuite et seulement ensuite je databind()

je vais essayer de comprendre ce que tu proposes
j'espere avoir été plus clair

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Regarde cet article : http://msdn2.microsoft.com/en-us/library/ms178472.aspx, il t'explique comment une application asp.net se déroule, je pense que cela pourrais te servir.

Si la sécurité "n'est pas un problème" tu peux aussi faire des response.redirect(lamemepage?querystring) aprés chaque sélection et suivant l'état des querystring tu fais toutes tes requetes dans le page_load donc les evenements changed ne te servirais qu'a faire un response.redirect vers la bonne page avec le bon querystring :-) 
Dans ce cas tu fais tes requetes vers la base dans le page_load seulement si la page ne vient pas d'un postback if(!Page.IsPostback) BindData(); inutile de charger des données pour un response.redirect ;-) (mais il va falloir que tu gardes le viewstate pour connaitre la value des elements qui ont changé)

<hr />Cyril - MVS - MCP
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

merci
pour info pour les non anglophone la page se trouve aussi ici
http://msdn2.microsoft.com/fr-fr/library/ms178472.aspx

pour le "pageinit" je ne crois pas que cela soit possible puisque c'est la meme page qui affiche toutes les etapes (les diff grid jusqu'a l'affichage final du detailview). je me trompe ? 
De plus pour faire rock & roll : je n'ai qu'une seule page en back qui change de nom en fonction des besoins (url rewriting).
Et en front j'ai egalement la meme chose : une seule page changeant de nom en fonction des pays, des magasins et des articles.

comment donc utiliser le page init dans ce cas la ?
faisons plus simple : je n'ai pas d'url rewriting ! le detailview est appelé par une autre page. je vais essayer.
sinon je peux peut etre dans le pageinit tester une variable boleene indiquant si je suis ou pas au stade de l'affichage du gridview.
a ce moment la je peux remplir toutes les variables necessaires a la construction de celui ci.

ceci en regardant les divers message d'erreurs (surtout en mode insert)
Inserting is not supported by data source 'Details' unless InsertCommand is specified.
pourtant j'ai bien construit ceci
InsertCommand---> INSERT INTO T_Famille (id_rayon, nom_famille_1, nom_famille_2, nom_famille_3, position, actif) VALUES (@id_rayon, @nom_famille_1, @nom_famille_2, @nom_famille_3, @position, @actif)
InsertParameters---> name =id
InsertParameters---> name =id_rayon
InsertParameters---> name =nom_famille_1
InsertParameters---> name =nom_famille_2
InsertParameters---> name =nom_famille_3
InsertParameters---> name =position
InsertParameters---> name =actif

j'ai plus l'impression que c'est dans la construction du detailsview que j'ai un probleme.
celui ci s'affiche parfaitement à l'ecran, les bouton de commandes aussi, mais je ne dois pas savoir les implementer.
une mauvaise connaissance de la classe detailsview ?

je ne dois pas re-injecter les parametres créés dans le controle.
dans tous les cas j'ai testé le pageinit avec une erreur previsible puisque qu'a la premiere ouverture de la pge je n'ai pas encore de serveur sql selectionné.

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Les postback multiple c'est dangeruex :p

Ce que je ferais dans ton cas.

La premiere fois, j'affiche les bases dispos dans le drop, lorsque celui ci change je fais un response.redirect("lapage.aspx?base=labasselectionne", true)

ensuite dnas le page_load de la page je vérifie si on a le querystring base, si oui je peuple le gridview, lorsque l'item change, je refais un response.redirect("lapage.aspx?base=labase&table=latable", true) etc... comme ca les evenements selectedindexchanged ne te servent qu'a rediriger la page ce qui udevrait supprimer pas mal de problème :-)

<hr />Cyril - MVS - MCP
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

cyril !
comme d'hab tes paroles sont le miel qui discipe les aigreurs de ma programmation (oh c'est bô non ? mdr)
effectivement tu avais raison des le debut
je te cite
"pour que les evenement soient lancé il faut que le controle soient présent dans l'arbre avant le page_load (c'est pour cette raison qu'il faut rajouté les controles dynamique dans le page_init) or dans ton cas le detailsView n'existe pas encore vu que le binding se fait sur l'evenement selectedindexchanged qui vient aprés le page_load ... "

le seul truc c'est qu'avant de comprendre ce que tu dis il faut que je "déquante" un peu

ceci dit voici comment j'ai procedé
 1) j'ai mis ma procedure de creation dynamique du detailview & son bind dans le page_init
2) dans le page init je teste une variable boolene pour savoir si j'ai toutes les conditions pour creer mon details view.

et  ca a marché une fois ! (apres plusieurs appuis sur le "selectionner" du gridmaitre)
depuis plus rien !
se pose une question : comment forcer la page a se recharger (dans l'état actuel pour pouvoir passer par le page_init ?)

ta reponse precedente semble donner la voie a suivre : je m'y attache
en tous les cas merci encore pour ton aide.
je ferais un tuto complet de la solution des que tout sera ok (en verifiant avec toi si je ne dis pas trop de betises)

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

ps a quoi sert l'argument "true" dans response.redirect("lapage.aspx?base=labasselectionne", true) ?

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
A générer une erreur est à remplir les fichiers de log *-)

En fait, ca permet de couper court à la page en killant son thread d'execution. Du coup asp.net le fait d'une telle facon qu'il lance une exception "non catché" qui arrive donc dans le Application_Error du global.asax ... :-/
Mais mis à part ce détails ca permet de gagner pas mal de ressource :-)

<hr />Cyril - MVS - MCP
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

grace a toi et a ta notion de page init je progresse
j'arrive meme jusqu'a la modification d'un enreg ! mais l'update plante
en fait a force de debugging je me suis appercu que lorsque je cliquais sur "edit" mon detailview perdait toutes les valeurs.
j'ai donc créé des variables session qui restituent les valeurs effacées.
les seules impossible a re-injecter sont Details.UpdateParameters et Details.InsertParameters


Exception Details: System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Web.UI.WebControls.Parameter'.


dans


            If Not Details.SelectCommand Is DBNull.Value And j <> 0 Then  'J reprenant le nombre de champs
                For i = 0 To j
                    nomvar = "Insert_Parameters_" & i
                    Details.InsertParameters.Item(i) = CType(Session(nomvar), WebControls.Parameter)
                Next
    


mais bon cela avance !

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
héhé :p je comprend pas vraiment l'erreur mais à mon avis c'est pas trés compliqué à trouver, tu enregistre un string dans ta variable session ...


j'ai pas le temps de regarder, mais tu peux créer une instance de WebControls.Parameter ? puis ensuite tu lui met ce qu'il faut dedans :-)





<hr />

Cyril - MVS - MCP
Messages postés
54
Date d'inscription
vendredi 1 février 2002
Statut
Membre
Dernière intervention
8 février 2007

yo ! Cyril
"créer une instance de WebControls.Parameter ? puis ensuite tu lui met ce qu'il faut dedans :-)"

impossible ! ou alors je ne sais pas faire
pourquoi ?
dans le
       
       
       


donc lorsque je cree l'update parameters (la premiere fois) je fais ceci 
 
          ' generation des Insert/UpdateParameters
                'update sans le champs index (donc table a partir de 1) j = nbre de champs ds ma table
                For i = 1 To j
                    Details.UpdateParameters.Add("name = " & """ & maTableNom(i).ToString & """, " Type=" & """ & maTableType(i).ToString  & """)
     'sauvegarde dans une variable session
                    Session("Update_Parameters_" & i) = Details.UpdateParameters.Item(i).ToString
                Next


    
plus tard dans mon page init j'essaye de recuperer ces variables sess
                Details.ConnectionString = Session("detail_CS")
                Details.SelectCommand = Session("Select_Command")
                Details.InsertCommand = Session("Insert_Command")
                Details.UpdateCommand = Session("Update_Command")



                For i = 0 To j
                    nomvar = "Insert_Parameters_" & i
                    'Dim instanssse As New WebControls.ParameterCollection  'beurk pas bô tout ca !
                    'instanssse.Add(nomvar, Session(nomvar)) ' Item(i) = CType(Session(nomvar), WebControls.Parameter)
                    Details.InsertParameters.Item(i) = Session(nomvar)
                Next

et la j'ai 2 problemes
1) Details.InsertParameters.Item est read only
2) Session(nomvar) est string d'ou l'erreur suivante
Exception Details: System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Web.UI.WebControls.Parameter'

j'ai cru comprendre que les var session prennent comme type, la valeur que tu leur donnes la premiere fois !
je vais donc essayer ceci
                    Session("Update_Parameters_" & i) = Details.UpdateParameters.Item(i)       '.ToString (sans le to string) en esperant que l'erreur de "cast" disparaisse !

Zen ! je dois rester Zen !

Léo dit dedZep
----------------------
pour acheter sur le Net il faut une carte bleue
Léo Tseu