2009-06-17 5 views
1

J'ai essayé de créer cette méthode d'extension. Fonctionne sauf que l'aide est le texte de rendu, pas le contrôle à la vue lorsque la page s'affiche:ASP.NET MVC Helper Extension Méthode ne rendant pas le texte en tant que contrôle

J'ai inclus en utilisant System.Web.Mvc.Html; en haut de ma classe d'aide qui contient cette méthode d'extension afin qu'elle comprenne helper.RadioButton.

public static string WriteTestControlToScreen(this HtmlHelper helper) 
{ 
    StringBuilder fields = new StringBuilder(); 
    fields.Append("<fieldset>"); 
    fields.Append("  <div class='formLabel'><span class='requiredText'>*</span><label>Background Color</label></div>"); 
    fields.Append("  <div class='formField'>" + helper.RadioButton("rbBackgroundColorWhite", 0, false) + "<label class='fieldInlineLabel' for=''>White</label></div>"); 
    fields.Append("  <div class='formField'>" + helper.RadioButton("rbBackgroundColorWhite", 0) + "<label class='fieldInlineLabel' for=''>Black</label></div>"); 
    fields.Append("</fieldset>"); 

    return fields.ToString(); 
} 

sortie dans la vue ressemble alors à ce (notez ce n'est pas rendu une RadioButton mais le traiter comme texte au lieu):

* Couleur de fond <% = Html.RadioButton ('rbBackgroundColorWhite', 0 , false)%> Blanc <% = Html.RadioButton ('rbBackgroundColorWhite', 0)%> Noir

+0

Comment appelez-vous WriteTestControlToScreen? –

+0

<% = Html.WriteTestControlToScreen()%> – PositiveGuy

Répondre

1

Je l'ai fait un peu farfouillé avec réflecteur, et j'ai remarqué que les méthodes d'extension MVC pour les champs d'entrée utilisent tous une La classe InputHelper, qui à son tour utilise une classe TagBuilder:

private static string InputHelper(this HtmlHelper htmlHelper, InputType inputType, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes) 
{ 
    ModelState state; 
    if (string.IsNullOrEmpty(name)) 
    { 
     throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name"); 
    } 
    TagBuilder builder = new TagBuilder("input"); 
    builder.MergeAttributes<string, object>(htmlAttributes); 
    builder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType)); 
    builder.MergeAttribute("name", name, true); 
    string str = Convert.ToString(value, CultureInfo.CurrentCulture); 
    bool flag = false; 
    switch (inputType) 
    { 
     case InputType.CheckBox: 

       //...etc. 

Ce qui suit est plusieurs instructions de cas couvrant le rendu supplémentaire requis pour les différents types d'entrée. Mais vous avez compris. Les gens de MVC ne sont pas en train de concaténer des chaînes; ils utilisent les méthodes MergeAttribute (et autres) pour faire le sale boulot pour eux. Ma conjecture est qu'il y a aussi une certaine compatibilité avec le navigateur. Ce que je suggère est que vous pourriez utiliser la classe TagBuilder pour construire votre code HTML, tout comme le font les gens de MVC.

+0

Mais à la fin, ne retournent-ils pas simplement une chaîne? c'est-à-dire renvoyer tagBuilder.ToString (TagRenderMode.SelfClosing); –

+0

Oui, mais voir ma deuxième réponse ci-dessous. –

+0

semble que je pourrais réutiliser InputHelper et juste passer le type d'entrée et ses attributs pour obtenir le même effet plutôt que de réinventer la roue et coder une méthode pour chaque type de contrôle en utilisant TagBuilder – PositiveGuy

1

Le problème avec votre code d'origine est que vous générez des balises <% =%> à un moment où MVC attend une sortie html littérale. En d'autres termes, il ne traite pas ces tags.

Envisagez de mettre votre code HTML dans un fichier .ASCX et de faire un RenderPartial.

+0

mais c'est une méthode d'aide, dites-vous mettre cela dans un fichier .ascx? Cependant, je ne veux pas toujours utiliser un .ascx pour tout mon HTML. – PositiveGuy

+0

Le problème est que MVC s'attend à ce que vos balises <%= %> soient dans la vue, pas dans la méthode d'assistance. Au moment où il arrive à la méthode d'assistance, il est trop tard. Le moteur de rendu ne passe pas par la méthode d'aide HTML recherchant ces balises. –

+0

Vous pouvez faire des méthodes d'assistance tout ce que vous voulez. Vous ne pouvez pas y mettre des balises <%= %>. –

1

Je sais que c'est un post plus ancien, mais il existe une solution élégante que j'ai utilisée lorsque je veux rendre les contrôles Telerik MVC entre eux. Cependant, il pourrait être utilisé avec n'importe quel assistant HTML. Il consiste à créer une aide en ligne dans le cshtml (pour rasoir) fichier comme indiqué ci-dessous:

<!-- This helper avoids nested literals with the sub-panel item --> 
@helper RenderPositionalResponsibilities() 
{ 
    Html.Telerik().PanelBar() 
     .Name("ContactSubItem") 
     .Items(subitem => 
     { 
      subitem.Add() 
       .Text("Positional Responsibilities") 
       .Content(
        @<text> 
         <div class="container scrollable" style="height: 150px;"> 
          @Html.CheckboxFor(model => model.IsTrue) 
         </div> 
        </text> 
       ) 
       .Expanded(true); 
     }) 
     .Render(); 
} 

Il peut alors être appelé comme indiqué dans la méthode contenu ci-dessous:

@{Html.Telerik().PanelBar() 
.Name("pnlUserForm") 
.ClientEvents(e => e.OnExpand("pnlUserForm_OnExpand").OnCollapse("pnlUserForm_OnCollapse")) 
.Items(i => 
{ 
    i.Add() 
     .Text("User Information") 
     .Expanded(true) 
     .Content(
      @<text> 
       <div> 
        @RenderPositionalResponsibilities() 
       </div> 
      </text> 
     ) 
} 
.Render(); 
} 

Cela pourrait être un meilleur correspondre pour les utilisateurs voulant créer une aide dans un but très précis. De plus, puisque vous créez l'assistant dans le fichier cshtml (pour rasoir), vous obtenez tous les intellisense pour les contrôles. Comment appelez-vous WriteTestControlToScreen?

Questions connexes