2009-07-10 6 views
2

Je travaille avec un système tiers pour implémenter certains formulaires dans un site Web.Le modèle correct pour transmettre des données aux contrôles enfants dans un contrôle serveur

Le système 3ème partie me fournit des définitions XML pour ces formulaires. par exemple. J'analyse ce XML dans un contrôle serveur et génère par programme un arbre de commandes. Les étiquettes des contrôles sont transmises dans le fichier XML.

Cela fait partie de notre proposition «d'injecter» de petits textes d'aide dans ce formulaire. Idéalement, je voudrais passer ces textes d'aide du balisage du contrôle de niveau supérieur pour que les non-développeurs (monkies HTML) puissent changer les textes d'aide, et les associer au champ par son ID. Quelque chose de tel

<controls:MyCrazyForm runat="server"> 
    <helpTexts> 
     <helpText for="field_Dob"> 
Some rambling nonsense to do with the DOB field 
     </helpText> 
     ... 
    </helpTexts> 
</controls:MyCrazyForm> 

Les contrôles sont analysés récursivement. Le formulaire crée un fieldset pour chaque segment, fieldsets crée plusieurs FieldXXX (où XXX = date, texte, liste déroulante etc) en fonction du type de données.

Les types FieldXXX créent un div puis plusieurs contrôles .net standard (TextBox, DropDownList, etc.) pour se rendre eux-mêmes. C'est à ce point, dans le div contenant que j'ai besoin de sortir le texte d'aide.

Ma question

Quelle est la « meilleure » façon d'obtenir ces textes de la commande de formulaire de niveau supérieur à ces contrôles enfants qui sont 3 ou 4 niveaux plus profonds dans l'arborescence de contrôle.

Il n'y aura jamais qu'un seul de ces formulaires sur une page. Est-ce que je devrais faire le niveau supérieur en Singleton et l'obtenir comme ça ...? Est-ce que je devrais passer une référence au formulaire dans chaque contrôle tout le long de l'arbre (cela semble désordonné)?

Suis-je des miles de la cible avec mon architecture de cette forme (bien que cela fonctionne vraiment bien pour le moment) et devrais-je envisager une autre méthode d'implémentation?

Merci

Répondre

1

Cela peut être plus compliqué au début, mais cela facilite la maintenance, pourquoi ne pas exécuter le fichier xml via un processeur xsl? Le fichier xslt affecterait les noeuds du texte d'aide de votre fichier helptexts aux noeuds de champ correspondants.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<form> 
    <segment> 
     <label>The header</label> 
     <fields> 
      <field> 
       <id>field_name</id> 
       <type>string</type> 
       <label>Name</label> 
       <required>1</required> 
      </field> 
      <field> 
       <id>field_Dob</id> 
       <type>Date</type> 
       <label>Date of Birth</label> 
       <required>1</required> 
      </field> 
     </fields> 
    </segment> 
</form> 
fichier XSLT

:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!-- Edited by XMLSpy® --> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="/form/segment/fields/field[id='field_name']"> 
    <xsl:copy> 
     <xsl:element name="helptext">This is a Name helptext.</xsl:element> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/form/segment/fields/field[id='field_Dob']"> 
    <xsl:copy> 
     <xsl:element name="helptext">This is a Date of birth helptext.</xsl:element> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="node() | text()"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

donne ceci:

<form> 
    <segment> 
     <label>The header</label> 
     <fields> 
      <field> 
<helptext>This is a Name helptext.</helptext> 
       <id>field_name</id> 
       <type>string</type> 
       <label>Name</label> 
       <required>1</required> 
      </field> 
      <field> 
<helptext>This is a Date of birth helptext.</helptext> 
       <id>field_Dob</id> 
       <type>Date</type> 
       <label>Date of Birth</label> 
       <required>1</required> 
      </field> 
     </fields> 
    </segment> 
</form> 

Ce fichier XML peut maintenant être analysé comme avant, mais maintenant vous pouvez obtenir le texte d'aide en même temps que vous générez les éléments de formulaire. Votre HTML monkies suffit alors d'éditer le fichier XSLT, ou vous incluez simplement un autre fichier:

<xsl:template match="/form/segment/fields/field[id='field_Dob']"> 
    <xsl:copy> 
     <xsl:element name="helptext"> 
     <xsl:copy-of select="document('field_Dob.txt')"/> 
     </xsl:element> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

Vous pouvez essayer en ligne XSL here

+0

Merci Ozan. Votre solution me semble la plus propre. Cela me permet de tout garder à peu près tel quel et d'injecter le texte d'aide dans mon document XML principal. bon travail! –

0

Qu'en traversant vers le haut les parents de la commande jusqu'à ce que vous trouviez un contrôle du certain type, ou avec une variable membre spécifique « ? » Textes d'aide Il s'agit d'une approche de programmation dynamique, mais pour certains éléments infrastructurels de la conception, tant que ces approches sont limitées, tout en étant bien commenté pourquoi cette approche de conception a été prise, je le trouverais acceptable.

Ce serait d'utiliser les API de réflexion, et une fonction d'assistance statique généralisée, comme

GetHelpTextFromParent(Control controlParent, string id) 

Ce serait alors inspecter le controlParent pour voir si elle avait les textes d'aide variables membres en son sein, puis regarder par id le texte d'aide.Sinon, il appelait récursivement GetHelpTextFromParent avec le parent de controlParent, jusqu'à une condition de terminaison appropriée. (Je mentionne "condition de terminaison appropriée" car il est probablement sous-optimal de garder ceci jusqu'à la fenêtre du bureau, vous voudrez peut-être terminer la récursion avant, mais ce sera un problème de test/débogage.)

0

Si vous utilisez XML dans un contrôle serveur et que vous générez par programme un arbre de commandes comment vous assurez-vous que les gars HTML gardent ces ID synchronisés? S'ils ont accès à ces XML, vous devriez peut-être les laisser ajouter helpTexts et non pas sur aspx.

Mais pour répondre à votre question, je suppose que vous êtes en train d'analyser le xml après que le balisage aspx a été lu et construit afin que vous puissiez indexer ces textes juste avant d'analyser le XML. Ensuite, lorsque vous construisez réellement votre arbre de contrôle dynamique, vous recherchez votre index par l'ID du contrôle défini dans votre source xml et vous le connectez à ce stade.

EDIT: D'accord, selon la façon dont vous construisez ces contrôles enfants, j'exposerais en interne tous ces textes d'aide en ligne comme une propriété indexée par l'ID de contrôle qui vous donnerait le texte d'aide ou une chaîne vide. Je ne suis pas sûr d'obtenir le MyCrazyForm.Instance cependant.

+0

Le code XML est fourni par une application tierce. Il n'est pas possible de modifier le XML dans un délai raisonnable. C'est pourquoi je souhaite l'augmenter de la fin ASPX –

+0

D'accord, maintenant je vois que vous incluez ces textes dans votre forme personnalisée. Vous devez donc gérer l'analyse XML et l'analyse HelpText dans votre contrôle de formulaire personnalisé. Comme je l'ai dit, analyser vos textes, puis analyser le XML de tierce partie et les combiner. – user134706

+0

Salut l'exécution. Je comprends cela, et je le fais actuellement. Ma question est de savoir quelle est la méthode des "paris" (easies, cleanest, flexible) pour obtenir les données analysées au plus haut niveau (dans le contrôle de la page) à travers 3 ou 4 niveaux de contrôle nécessaire. –

0

Je propose de créer une interface comme celui-ci

interface IHelpTextProvider 
{ 
    Dictionary<string, string> HelpTexts 
    { 
     get; 
    } 
} 

Ensuite, le contrôle de votre formulaire peut implémenter cette interface et passer une référence à cette interface lors de la création fieldsets et des contrôles FieldXXX. Alternativement, vous pouvez faire comme polyglotte suggéré et quand le texte d'aide est nécessaire, le contrôle FieldXXX va récursivement à travers ses parents jusqu'à ce qu'une interface IHelpTextProvider parent est trouvée.

0

Vous pouvez créer un événement dans le contrôle serveur pour qu'il soit déclenché chaque fois qu'il le souhaite/nécessite un texte d'aide pour un champ donné. Le formulaire peut connecter un gestionnaire d'événements et y répondre. De cette façon, vous n'avez pas besoin de passer un objet pour permettre au serveur de contrôler l'accès à l'information. Pour cela, nous devons faire trois choses.

Créer une EventArgs classe:

class HelpTextEventArgs : EventArgs 
{ 
    public string Text { get; set; } 
    public string FieldId { get; private set; } 
    public HelpTextEventArgs(string fieldId) 
    { 
     FieldId = fieldId; 
    } 
} 

Créer l'événement dans le contrôle du serveur:

public event EventHandler<HelpTextEventArgs> HelpTextRequested; 

protected void OnHelpTextRequested(HelpTextEventArgs e) 
{ 
    EventHandler<HelpTextEventArgs> evt = this.HelpTextRequested; 
    if (evt != null) 
    { 
     evt(this, e); 
    } 
} 
// wrapper for the event raising method for easier access in the code 
public string GetHelpText(string fieldId) 
{ 
    HelpTextEventArgs e = new HelpTextEventArgs(fieldId); 
    OnHelpTextRequested(e); 
    return e.Text; 
} 

... et mettre en place un gestionnaire d'événements sous la forme qui peut accéder aux textes d'aide:

private void Page_Load(object sender, EventArgs e) 
{ 
    ServerControl.HelpTextRequested += ServerControl_HelpTextRequested; 
} 

private void ServerControl_HelpTextRequested(object sender, HelpTextEventArgs e) 
{ 
    e.Text = FindHelpText(e.FieldId); 
} 

En utilisant cette approche, le code fonctionnera bien même si le formulaire d'hébergement ne fournit pas l'aide service xt; le contrôle serveur ne dépend pas du fait qu'un gestionnaire d'événements est connecté.

1

En plus d'examiner les différentes façons de transmettre l'information entre les contrôles, comme les autres réponses l'ont indiqué, je pense qu'une approche différente peut être utile, selon les particularités de votre cas. Un problème analogue à celui que vous décrivez - associer un texte spécifique à certains contrôles sur un formulaire - a été résolu pour le cas plus général de l'internationalisation, avec Ressources. Je sais que ceci est différent des autres réponses et pas directement de ce que vous avez demandé dans votre question, mais les ressources semblent assez bien répondre aux besoins, comme décrit ci-dessous. Plutôt que de répondre à votre question spécifique sur la circulation de l'information entre les contrôles, j'essaie de considérer le résultat final que vous essayez d'atteindre.Allez-y doucement si j'ai mal compris quelque chose :-)

  1. Chaque forme et champ dans un formulaire ont une identité unique. Par conséquent, un ID de ressource peut être construit uniquement à partir du formulaire et du champ.
  2. Un fichier source de ressources est simplement XML, complètement séparé des spécificités de l'interface utilisateur et peut être donné à des non-développeurs pour remplir avec le texte d'aide pertinent. Si vous modifiez l'interface utilisateur, ce fichier ne doit pas nécessairement changer .
  3. Au moment du rendu, vous pouvez simplement obtenir la ressource pour un champ dans un formulaire en utilisant son ID de ressource et incorporer le texte dans l'interface utilisateur comme vous le souhaitez.
  4. Comme la même approche est utilisée pour I18N/L10N, elle est bien documentée, bien comprise, déclarative, simple et performante.
0

Comme Ozam suggéré, vous pouvez utiliser XSL.

Un fichier XML séparé avec la structure similaire à celle du fichier xml tiers qui contient helpText par nœud XML serait bon & vous devrez peut-être les fusionner (?) D'une certaine manière.

Je ne sais pas si cette aide en aucune façon, du tout.

Questions connexes