2011-10-19 8 views
9

Se sto passando HtmlAttributes in un modello, come questo:HtmlAttributes Aggiunta a Template

@Html.DisplayFor(m => m.FirstName, new { htmlAttributes = new { @class = "orangetxt strongtxt" } }) 

Nel mio modello, come faccio a iniettare questi nel mio HTML:

<span @ViewData["htmlAttributes"]>@Model</span> 

Questo quasi funziona, ma fa cose piuttosto strane, quindi presumo che questa non sia la strada da percorrere.

Mi rendo conto che posso ottenere questo risultato con un metodo di estensione HtmlHelper per il rendering dell'intero elemento HTML (in questo caso span) e passare gli attributi in questo modo, ma c'è un modo per eseguire il rendering direttamente in un elemento HTML , come nell'esempio sopra?

risposta

8

Il metodo di estensione di seguito mi permetterà di convertire HtmlAttributes in una stringa:

public static MvcHtmlString RenderHtmlAttributes<TModel>(
     this HtmlHelper<TModel> htmlHelper, object htmlAttributes) 
    { 
     var attrbituesDictionary = new RouteValueDictionary(htmlAttributes); 

     return MvcHtmlString.Create(String.Join(" ", 
      attrbituesDictionary.Select(
       item => String.Format("{0}=\"{1}\"", item.Key, 
       htmlHelper.Encode(item.Value))))); 
    } 

Poi, per rendere loro all'interno del tag, posso solo fare questo: risposta

<span @Html.RenderHtmlAttributes(ViewData["htmlAttributes"])>@Model</span> 
+0

Hmm potrei sbagliarmi qui, ma il tuo uso previsto come basato sulla domanda, a me sembra non funzionerà .. puoi forse includere come stai usando l'aiutante – Ahmad

0

DisplayFor() viene utilizzato per il rendering del modello che corrisponde al tipo di proprietà.

modelli di visualizzazione sono file .cshtml all'interno /DisplayTemplates cartella che a sua volta si trova all'interno di una cartella vista (vale a dire qualsiasi cartella da casa, Condiviso o anche un controller specifico).

Un esempio.

Se hai un String.cshtml modello come questo all'interno /Vista/comune:

@model String 

@if (string.IsNullOrEmpty(Model)) { 
    <span>(no string)</span> 
} 
else { 
    <span>@Model</span> 
} 

Ogni volta che si chiama DisplayFor() per una proprietà stringa:

DisplayFor(model => model.MyStringProperty); 

E ' rende il modello di conseguenza al valore della stringa. Puoi essere più specifico e inserire /DisplayTemplates all'interno di una specifica cartella di visualizzazione e solo le chiamate da tali viste sono influenzate dal modello.


Nel tuo caso si può essere ancora più specifico e chiamare DisplayFor() con un modello particolare.

Supponiamo di avere un modello per una particolare proprietà, denominato MyPropertyTemplate.cshtml. Si potrebbe chiamare DisplayFor() come questo:

DisplayFor(model => model.MyProperty, "MyPropertyTemplate"); 

E loro, all'interno di tale modello si può avere tutto quello HTML attributi desiderati.

@model MyProperty 

<span class="orangetxt strongtxt">@MyProperty.ToString()</span> 

PS: Quando non trova un modello Credo che solo chiamate model.Property.ToString() senza ulteriore html.

FYI: EditorFor(), ad esempio, funziona in modo simile ma utilizza la cartella /EditorTemplates.

+1

Grazie. Capisco come funzionano i template, ho solo bisogno di capire come passare in HtmlAttributes a un template e renderli come nell'esempio sopra, senza doverli codificare in un nuovo modello. Voglio che siano più flessibili. –

+1

Il problema con i template, Jerad, è dove vanno gli htmlAttributes? Potresti avere un modello enorme con molte div e cosa no. Quello che vuoi fare sarà molto personalizzato e fondamentalmente comporta la scrittura dei tuoi metodi HtmlHelper per l'output con l'htmlAttributes personalizzato. – Buildstarted

+1

Vero, capisco che con i modelli complessi, è difficile sapere a cosa si applicherebbe il 'htmlAttributes'. Nel mio caso, sarà sempre applicato all'elemento che circonda immediatamente il valore del modello. Se volevo, ad esempio, includere un'altra opzione per applicare attributi personalizzati all'etichetta, potrei aggiungere il supporto per 'labelHtmlAttributes', ad esempio. –

1

Prova a modificare,

@Html.DisplayFor(m => m.FirstName, 
       new { htmlAttributes = "class = orangetxt strongtxt"}) 

Questo renderà una stringa, mentre la versione ha fatto cose strane, reso {} come parte dell'output.

+0

Questo è vicino, ma ancora non esattamente quello che sto cercando. Non voglio davvero dover gestire tutte le conversioni e la codifica delle stringhe. In realtà ho trovato un metodo di estensione per il rendering degli attributi HTML e lo pubblicheremo di seguito. –

+0

@JeradRose - in base a ciò che hai corrente, non cambia nulla tranne la chiamata effettiva a Displayper quindi nessuna conversione e codifica – Ahmad

+1

Sì, ma quanto sopra era solo un esempio. Potrei avere casi in cui gli attributi devono essere un po 'più complessi e richiederanno virgolette. Ad esempio, se ho bisogno di includere 'class =" orangetxt strongtxt "id =" myId "', allora inizia a diventare un po 'pazzo usando la tua soluzione. –

3

Jerad di Rose è buono, ma mi sono imbattuto in due problemi:

  • Non converte i caratteri di sottolineatura in trattini in attributo nomi
  • non gestisce alcun valore attribuisce grazia

Per affrontare prima il problema, utilizzare HtmlHelper.AnonymousObjectToHtmlAttributes.

Qui di seguito è la mia modifica del metodo di Jerad:

public static MvcHtmlString RenderHtmlAttributes(this HtmlHelper helper, object htmlAttributes) 
{ 
     if (htmlAttributes == null) return new MvcHtmlString(String.Empty); 
     var attrbituesDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 
     return new MvcHtmlString(String.Join(" ", attrbituesDictionary.Select(item => string.IsNullOrEmpty((string)item.Value) ? String.Format("{0}", item.Key) : String.Format("{0}=\"{1}\"", item.Key, helper.Encode(item.Value))))); 
}