Masterpage / UserControl / UpdatePanel

Signaler
Messages postés
8
Date d'inscription
mercredi 11 avril 2007
Statut
Membre
Dernière intervention
27 avril 2007
-
Messages postés
4
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
26 mai 2008
-
Bonjour,

J'ai un 'léger' soucis avec mes UpdatePanels, je m'explique :

J'ai une masterpage qui contient un UserControl. Celui-ci contient un UpdatePanel et dans ce panel, j'y ai placé un LinkButton invisible que je compte utiliser pour rafraichir ce même panel manuellement (un peu comme l'exemple de Cyril sauf que le bouton est à l'intérieur du panel).

Ensuite, dans ma masterpage, j'ai un ContentPlaceHolder qui affiche le contenu de mes pages. Plusieurs de mes pages contiennent un autre UserControl qui, lui aussi, contient un UpdatePanel. Dans ce même panel, j'y ai placé un gridview avec un bouton pour chaque ligne. Le code de l'event Click du bouton fait appel à mon WebService (WCF pour infos mais peu importe) et c'est là que je dois rafraichir le premier UpdatePanel dont j'ai parlé.

En résumé :



MasterPage contient :
   - UserControl1 qui contient :
      > UpdatePanel1
         > LinkButton1
   - ContentPlaceHolder

Page contient :
   - UserControl2 qui contient :
      > UpdatePanel2
         > GridView1
            > LinkButton2

Mon LinkButton2 doit faire un traitement AVANT de rafraichir UpdatePanel1.

Bon alors, j'ai utilisé la solution de Cyril mais modifiée, c'est-à-dire :

Dans l'event de mon LinkButton2, après mes traitement, j'ai utilisé ScriptManager.RegisterStartupScript et comme code JS, j'ai mis ceci : $get('ManualUpdate').click();


Ca marche MAIS il faut click 2x sur LinkButton2 :p c'est assez embêtant. Et après quelques tests, il semblerait que les updates sont décalés, c'est-à-dire que la première fois que je click, le traitement se fait bien mais pas d'update. Seconde fois, traitement impec aussi et là ça update mais ça affiche la valeur du premier update. 3ème fois, traitement impec et valeur du 2ème update... et ainsi de suite...

J'ai testé la méthode barbare : mettre le .click() 2x -> sans résultat (non sans rire :D)


mais sinon, j'ai pas d'idée :s


Si quelqu'un en aurait une, je suis -très- ouvert ^^

Merci d'avance.

PS: j'espère avoir été assez clair ^^
PS²: je peux aussi vous mettre dans le contexte, histoire de mieux comprendre le pourquoi du comment

9 réponses

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

le problème n'est pas l'UpdatePanel mais les postback classiquement.

Quand tu click sur le bouton ($get('ManualUpdate').click(); (que je te conseille de remplacer en String.Format("$get('{0}').click();", manualUpdate.ClientID) mais bref)) tu vas lancer une requete http classique à ASP.net qui va la traitement normalement, page_init, page_load, click sur le bouton et rendering modifié. Apparemment ton UC se construit dans le Page_load puis tu modifies des données, il faut donc refaire le traitement du page_load, généralement on fait une méthode BindData(); que l'on appelle seulement en cas de besoin : if(!ispostback)BindData(); viod button_click(){BindData(); } ...

<hr />Cyril - MSP - MCTS ASP.net & SQL
Messages postés
6
Date d'inscription
mardi 24 avril 2007
Statut
Membre
Dernière intervention
9 juillet 2007

Bonjour Ludo,
ayant eu des soucis avec les evenements avec des WebForm dernièrement j'ai lu pas mal de documentation et de pages de forum, et je crois me rappeller qu'a plusieurs reprise (meme sur MSDN) il est ecrit que la propriété AutoEventWireup présente dans les lignes qui figurent en haut de tes user control (et des pages aspx aussi d'une facon similaire) peut poser des problèmes lorsqu'elle est à "true" et faire intervenir 2 fois un evenement. Il m'était de plus arrivé qu'un script appeller dans un evenement s'effectue 2 fois au lieu d'une pour moi.
Alors essaye de regarder cette propriété et de la changer peut etre ton problème vient il de là... ou peut etre pas, et dans ce cas je suis peut etre hors sujet ^^' Enfin tu perds pas grand chose à tester.
Bonne chance à toi dans tous les cas.
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Je ne pense pas que le problème vienne de là, j'en suis meme quasi certains :-)

en gros AutoEventWireup permet de s'abonner automatiquement à des controles : d'ailleurs je viens de repenser que j'avais écrit sur le sujet :
http://blogs.codes-sources.com/cyril/archive/2006/07/18/AutoEventWireup-C-et-ASP-net.aspx 

<hr />Cyril - MSP - MCTS ASP.net & SQL
Messages postés
8
Date d'inscription
mercredi 11 avril 2007
Statut
Membre
Dernière intervention
27 avril 2007

Bonjour à vous et merci pour vos réponses :)

@Cyril :
pour le String.Format("$get('{0}').click();", manualUpdate.ClientID); --> pas possible (en tout cas pour le moment ^^), je ne connais pas le (link)bouton "manualUpdate" à partir du UserControl2 mais bon soit, c'est un détail

pour la 'construction' de l'UC et bind des données, j'ai pas trop compris ce que tu voulais dire, si tu pouvais éclaircir stp :)

je vais faire quelques tests sous VS avec breakpoints pour voir ce qu'il fait à ce niveau.

@Onizukasan :
mmmh disons que dans le cas où l'event s'exécuterait 2x, ça ne changerait rien aux données. Le traitement que je fais est en fait une simple update dans la DB, par l'intermédiaire du WebService. Donc que je fasse le traitement 1x ou 2 avec les mêmes données à modifier, le résultat sera le même. Merci quand même pour ta réponse ^^

---------

Bon je vais quand même donner le contexte :

Je dois réaliser ce projet dans le cadre de mon stage. Ce projet est un e-commerce sur base d'un système ERP. Je ne vais pas m'étendre sur les détails...

Le UserControl contenu dans la MasterPage est en réalité appelé "OrderHeaderControl" ou entête d'une commande. Pq ce usercontrol dans la masterpage ? tout simplement car quand une commande est en cours, l'entête doit apparaître sur chaque page et pour éviter les répétitions, je l'ai placé dans la masterpage.
Dans cette entête, sont contenues les diverses infos de la commande, comme le nombre de positions, la référence de la commande, etc.... et..... le prix total !

La page proprement dite contient la liste des articles que le client a ajouté à la commande. Cette liste est un GridView qui se trouve dans un UserControl, qui s'appelle "OrderItemsGridViewControl". Pq ? tout simplement car j'ai besoin exactement du même contrôle (pour des articles également) à d'autres endroits dans le site. donc je l'ai codé un maximum modulable.

Le LinkButton2 dont j'ai parlé dans mon premier post est enfait le bouton "Modifier" du GridView (note que c'est pareil pour le bouton "Supprimer" mais c'est plus facile de tester sur modifier ^^). Il y a donc une TextBox à côté de ce bouton qui est enfait la quantité d'article à commander. (voilà pour ce que je disais ici plus haut, si l'event du bouton est lancé 2x -> résultat identique)

Donc comme vous l'avez normalement compris ^^ dès que je click sur modifier, le prix total de l'entête devrait se mettre à jour.

---------

Donc mon problème de départ, c'est que je ne sais pas accèder à l'UpdatePanel contenu dans OrderHeaderControl à partir de OrderItemsGridViewControl, et c'est pour ça que je compte(ais) utiliser du JS pour refresh.

J'ai essayé FindControl mais sans succès :/ il me retourne null à chaque fois
Des casting genre (ASP.ctrl) mais il ne trouve pas le namespace..

dsl pour cette masse de texte lol et encore merci pour votre aide (surtout Cyril ! c'est pas la première fois :)
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Le problème ne vient pas des UpdatePanel, oublie les UpdatePanels.

Ce qu'il faut avoir en tete c'est le cycle de vie d'une page ASP.net. Tout d'abord la page passe page l'evenement page_preinit, puis page_init puis page_preload (entre le 2, le viewstate se recharge) puis le page_load qui déclenche tous les evenements load de tous les contrôles présent dans la page, puis si la page vient d'un postback alors il va déclencher (par exemple) l'évenement click du button, puis vient l'event prerender et la phase de rendering, ca se passe aussi bien pour les requetes normales, les postback, ou les asyncpostback (updatepanel) dans le cas d'un AsyncPostBack le rendering est modifié pour conservé seulement le HTML des UpdatePanels à rafraichir.

Le problème vient du fait que l'evenement load est déclenché avant le click.

- Je fais ma premiere requete
   - les events load sont déclenché, les gridviews & co sont bindés, les données sont dans les controles 
   - le rendering arrive est génére du HTML à partir des données
- je click sur mon button
   - event load OK, je charge mes données dans la base et je met ca dans mon controle
   - click sur le buton mis à jour de la bdd
   - rendering à partir des données obtenus avant l'update
-je RE click sur le button 
  - event load OK, je charge mes données qui ont été modifié avant par l'event click
  - je remodifie mes données
   - rendering à partir des données présent dans la base effectué à partir des données du premier click

J'espere que c'est plus clair :p

Donc lorsque tu clicks il faut rebinder ton gridview

<hr />Cyril - MSP - MCTS ASP.net & SQL
Messages postés
8
Date d'inscription
mercredi 11 avril 2007
Statut
Membre
Dernière intervention
27 avril 2007

ok c'est très clair merci ^^

mais je ne comprends toujours pas pq rebinder mon gridview ^^ car ses données sont correctes (vu que l'update dans la db est correcte) et quand je click, rien ne doit changer à ce niveau

(note que pour le moment je fais le bind des données dans la page puis appel à ma fct Bind() du contrôle, hors le code de l'event se trouve dans ce contrôle..)

ce que je comprendrais, c'est rebind l'entête de la commande dans le bouton (afin que le contrôle contiennent les données mises à jour) mais à partir du contrôle OrderItems je n'arrive pas à accèder au contrôle d'entête..

-------

bon j'ai testé quelque chose.. j'ai mis ceci comme script, après mon traitement dans l'event du bouton :

ScriptManager.RegisterStartupScript(btn, btn.GetType(), "ohmanualupdate",
"document.getElementById('ctl00_ohcCurrentOrder_ManualUpdate').click();", true);

et après, je fais un second register pour afficher une alerte :

ScriptManager.RegisterStartupScript(btn, btn.GetType(), "alert", "alert('modifié');", true);

enfait je peux mettre l'alerte après le document.getElementById, ça donne le même résultat mais j'ai préféré les scinder.

bizzarement, ça semble fonctionner à tous les coups sous IE7 ! ($get avec le clientid en dur semble aussi fonctionner, pour rappel je n'utilisais pas clientid avant mais le serverid, en l'occurence ici "ManualUpdate") Le prix total -correct- apparait bien et ce avant l'alerte.

2 problèmes :
- sans l'alerte, même prob qu'avant (décalé)
- erreur JS : Sys.InvalidOperationException: ScriptLoader.loadScripts cannot be called while the ScriptLoader is already loading scripts. (elle vient même si je ne scinde pas le click et l'alerte en 2 appels de register)

???? :D j'ai beau essayer de comprendre (surtout le truc de l'alerte !!!! comme on dit en anglais, WTF?! :p) mais n'y arrive pas :/

sous Firefox, ça réagit différemment... l'alerte s'affiche et tjrs pas d'update du prix total... je click sur Ok et boom postback... et là bien sûr le prix est rafraichit vu que la page s'est rechargée mais bon... lol
(pas remarqué d'erreur JS)

sous Opera, l'alerte s'affiche mais carrément pas d'update :s (le bouton ManualUpdate fonctionne pourtant très bien quand on click dessus à la main... :p)
(idem ici, pas vu d'erreur JS)

c'est quand même louche tout ça et après ça, j'ai encore plus de doutes que ça vienne du bind de mes données :o maintenant je peux me tromper
Messages postés
4
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
26 mai 2008

Bonjour Cyril et merci de faire partager tes connaissances et ton expérience.

Pour ma part, j'ai un UpdatePanel avec deux boutons et j'avais codé dans la partie Evenement 'Load' de la page l'affichage dynamique des données de l'updatepanel (requêtes dans la base de données + construction d'un tableau html pour ensuite l'afficher dans un Panel de l'UpdatePanel).

Je rencontrais donc le problème légèrement identique que ludo. Et en ayant suivi ton post expliquant les différents appels successifs des fonctions évènementielles, j'ai fini par ajouter mon code d'affichage dynamique des données directement dans l'évènement PreRender de la page et cela fonctionne.

Je voulais juste avoir la confirmation que cela est propre...

Merci encore

Florian
Messages postés
6814
Date d'inscription
dimanche 15 décembre 2002
Statut
Modérateur
Dernière intervention
13 octobre 2010
28
Bonjour,

dans le prerender ??? J'ai envie de dire que si ca marche c'est une solution correcte, mais ce n'est pas ce qu'il y a de plus propre.


Tout d'abord pourquoi construire un HTMLTable plutot qu'utiliser un Gridview ? C'est vrai que l'utilisation d'un HTMLTable au niveau du PreRender ne devrait pas poser trop de soucis, mais si tu créais des contrôles nécessitant un postback ou persistence des données (viewstate) alors ca aurait été le drame ;)


<hr />
Cyril - MSP - MCPD ASP.net & MCTS SQL - Consultant indépendant
Messages postés
4
Date d'inscription
mercredi 5 février 2003
Statut
Membre
Dernière intervention
26 mai 2008

Bonjour Cyril,

  J'ai créé un HTML Table car les colonnes affichées différent du jour, de l'heure et du contenu de la base de données donc le gridview ne me convenait pas car il propose un affichage standard des colonnes. Le problème désormais que je rencontre se rapproche évidemment de ta dernière remarque, à savoir que je crée également dynamiquement des imagebutton dans certaines cellules du tableau et le AddHandler ne fonctionne pas car trop tard dans le cycle de vie de la page.. Et je me sens bloqué actuellement...

Si tu as une idée..

Merci

Florian