Je travaille sur un contrôle de quiz sur asp.net avec des questions et des options créées de manière dynamic. Le contrôle principal est essentiellement un conteneur contenant toutes les questions. En mode Conception, les utilisateurs peuvent append des questions via un éditeur de collection personnalisé. Chaque fois que j’ajoute une question à la liste de l’éditeur de collection, cela génère une étiquette de question pour moi. Chaque object de question contient une étiquette et une quantité n d’objects Option qui héritent du contrôle Radiobutton. Chacun de ces objects Option représente à son tour une option que l’utilisateur peut sélectionner pour chaque question.
Tout cela fonctionne sauf que je suis maintenant à la partie où je veux pouvoir lire la valeur Checked de chaque radiobutton. Quand je veux implémenter ce quiz dans une page et vérifier les questions, je veux mettre un bouton dans cette page et appeler la fonction suivante qui est à l’intérieur du contrôle
$
public Ssortingng checkQuestions() { if (questions != null) { foreach (Question question in questions) { options = question.readOptions(); int i = 0; foreach (Option option in options) { testLabel.Text = option.Checked.ToSsortingng(); // test purposes only } } } return errors; }
Cependant, une fois que je sélectionne un bouton radio et que je clique sur le bouton d’envoi, la valeur Checked sera toujours fausse pour toutes les options. Fondamentalement, il perd sa valeur vérifiée après un Postback et je suis juste coincé dans essayer de le résoudre. J’apprécierais que quelqu’un me dirige dans la bonne direction.
À première vue, je vérifie deux choses. Tout d’abord, assurez-vous d’implémenter IPostBackDataHandler
. pour cela, vous devez implémenter deux méthodes, LoadPostData
et RaisePostDataChangedEvent
. À première vue, le premier est probablement la source de votre problème.
LoadPostData
prend les chaînes postDataKey
et NameValueCollection
postCollection
et renvoie une NameValueCollection
postCollection
indiquant si la valeur a été modifiée à la suite de la publication. Vous n’avez pas besoin d’implémenter cela comme prévu initialement par .Net, par exemple, j’ai créé un contrôle qui contenait plusieurs boutons radio (qui, pour des raisons sans importance, ne pouvait pas simplement être un contrôle RadioButtonList
) et s’est donc assuré qu’ils ont tous été nommés par une ssortingng GroupName
propriétés ssortingng GroupName
et ont inspecté la postCollection
pour ce GroupName
:
public bool LoadPostData(ssortingng postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { bool oldValue = _isChecked; postCollection = HttpContext.Current.Request.Form; // See note below _isChecked = (postCollection[this.GroupName] == this.Text); return oldValue == _isChecked; }
Vous remarquerez que je redéfinis la postCollection
ici; C’est parce que postCollection
ne contient qu’un sous-ensemble de HttpRequest.Form
correspondant à ce que ASP.Net pense que votre contrôle devrait se préoccuper. Comme vous construisez également un contrôle composite ici, vous voudrez probablement faire de même.
Ne vous inquiétez pas si cela ne fonctionne pas du premier coup; cela vaut la peine de parcourir ce qui est passé dans cette méthode en mode débogage (ou de sortir des choses dans HttpContext.Trace
, que je trouve souvent plus facile) pour voir pourquoi votre code n’est pas tout à fait ce dont vous avez besoin.
Une dernière chose: LoadPostData
n’est appelé que si le formulaire posté contient un champ avec un nom qui correspond à l’ UniqueID
de votre contrôle. Comme votre contrôle est un contrôle composite, vous voudrez peut-être un peu cow-boy, comme ceci:
protected override void Render(HtmlTextWriter writer) { base.Render(writer); writer.WriteBeginTag("input"); writer.WriteAtsortingbute("type", "hidden"); writer.WriteAtsortingbute("name", this.UniqueID); writer.WriteAtsortingbute("value", "post"); writer.Write(" />"); }
C’est un sale bidouillage, mais ça va marcher; o)
Si la gestion manuelle de la publication ne résout pas votre problème, il se peut que vous deviez modifier le statut d’affichage de votre contrôle. Ne vous inquiétez pas, c’est loin d’être aussi effrayant qu’il y paraît, à condition de respecter quelques règles simples.
Pour gérer votre état d’affichage manuellement, il vous suffit de redéfinir deux méthodes appelées, de toute évidence, LoadViewState
et SaveViewState
. Le premier prend un object
de viewstate à gonfler et le second retourne cette même structure d’ object
. Si vous SaveViewState
votre remplacement SaveViewState
renvoyer quelque chose contenant la structure dont vous avez besoin pour enregistrer toutes les propriétés importantes devant LoadViewState
persistantes, vous devez simplement le gonfler à nouveau dans votre méthode LoadViewState
.
Voici où le premier des tours rusés se pose. Il existe certains types de données que vous devez utiliser pour enregistrer viewstate et vous ne devez jamais utiliser d’autres types (car les autres types sont stockés de manière vraiment inefficace). Les types qui vous seront probablement les plus utiles sont System.Web.UI.Pair
, System.Web.UI.Triplet
et nos anciens amis System.Collections.ArrayList
et System.Collections.Hashtable
. Les paires et les sortingplets stockent simplement deux ou trois valeurs de type object
; ArrayLists est en réalité un List
.
Je suppose que dans votre cas, vous voudrez probablement stocker soit (1) une ArrayList de drapeaux booléens, en mémorisant le “contrôle” de vos radiobuttons, soit (2) une ArrayList de chaînes ou d’entiers, en stockant les identifiants ou index de les boutons radio vérifiés.
Dans le contrôle que j’ai mentionné précédemment, je devais simplement stocker le contrôle et la propriété Text
. SaveViewState
méthodes LoadViewState
et SaveViewState
ainsi:
protected override void LoadViewState(object savedState) { Pair state = savedState as Pair; if (state != null) { _isChecked = state.First as Nullable ?? false; this.Text = state.Second as ssortingng; } } protected override object SaveViewState() { return new Pair(_isChecked, this.Text); }
Encore une fois, si cela ne fonctionne pas du premier coup, vous souhaiterez certainement parcourir le code ou jeter des éléments dans la trace. Il est important de noter que vous souhaiterez probablement éviter de lancer des exceptions à partir de ces méthodes, au cas où votre état de vue serait corrompu ou inexistant, ou quelque chose du genre.
Il y a quelques articles très utiles pour lesquels je garde un signet lorsque je me mêle de viewstate. La première explique pourquoi vous ne devriez stocker que certains types dans l’état d’affichage (comme avec ArrayList
et Hashtable
, plutôt que List
et Dictionary
), et la seconde est une bonne explication détaillée de la manière dont tout cela est utilisé. Les choses de viewstate fonctionnent réellement.
J’espère que tout cela aide à résoudre votre problème.