Asp Contrôle composite de contrôle enfant (radiobutton) perdant la valeur vérifiée

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.

Gestion manuelle de la publication

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 mise en garde rapide

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)

Gestion manuelle de viewstate

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.

En savoir plus sur viewstate

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.

  1. Ne laissez pas le BinaryFormatter y arriver!
  2. Vraiment comprendre ViewState

J’espère que tout cela aide à résoudre votre problème.