Come creare ViewComponents annidati in monorotaia e NVelocity?
-
03-10-2019 - |
Domanda
Mi è stato chiesto di aggiornare il menu su un sito web manteniamo. Il sito web utilizza Castello Windors monorotaia e NVelocity come modello. Il menu è attualmente resa utilizzando sottoclassi su misura di ViewComponent, che rendono gli elementi li. Al momento non esiste un solo livello (orizzontale), quindi il meccanismo attuale è soddisfacente.
Mi è stato chiesto di aggiungere menù a scomparsa per alcuni dei menu esistenti. Poiché questa è la prima volta che ho visto monorotaia e NVelocity, io sono un po 'perso.
Ciò che esiste attualmente:
<ul>
#component(MenuComponent with "title=Home" "hover=autoselect" "link=/")
#component(MenuComponent with "title=Videos" "hover=autoselect")
#component(MenuComponent with "title=VPS" "hover=autoselect" "link=/vps")
#component(MenuComponent with "title=Add-Ons" "hover=autoselect" "link=/addons")
#component(MenuComponent with "title=Hosting" "hover=autoselect" "link=/hosting")
#component(MenuComponent with "title=Support" "hover=autoselect" "link=/support")
#component(MenuComponent with "title=News" "hover=autoselect" "link=/news")
#component(MenuComponent with "title=Contact Us" "hover=autoselect" "link=/contact-us")
</ul>
E 'possibile avere MenuComponents nidificate (o una nuova SubMenuComponent) qualcosa come:
<ul>
#component(MenuComponent with "title=Home" "hover=autoselect" "link=/")
#component(MenuComponent with "title=Videos" "hover=autoselect")
#blockcomponent(MenuComponent with "title=VPS" "hover=autoselect" "link=/vps")
#component(SubMenuComponent with "title="Plans" "hover=autoselect" "link=/vps/plans")
#component(SubMenuComponent with "title="Operating Systems" "hover=autoselect" "link=/vps/os")
#component(SubMenuComponent with "title="Supported Applications" "hover=autoselect" "link=/vps/apps")
#end
#component(MenuComponent with "title=Add-Ons" "hover=autoselect" "link=/addons")
#component(MenuComponent with "title=Hosting" "hover=autoselect" "link=/hosting")
#component(MenuComponent with "title=Support" "hover=autoselect" "link=/support")
#component(MenuComponent with "title=News" "hover=autoselect" "link=/news")
#component(MenuComponent with "title=Contact Us" "hover=autoselect" "link=/contact-us")
</ul>
devo disegnare il sottomenu (ul e li elementi) all'interno del metodo sottoposto a override Render su MenuComponent, in modo da utilizzare derivati ??ViewComponent nidificati non può funzionare. Vorrei un metodo di mantenere il metodo essenzialmente dichiarativo per la creazione di menu, se possibile.
modifica: posso usare Context.RenderBody () per rendere i derivitives ViewComponent nidificate, ma sono in fase di rendering prima che il genitore. Credo che il lacerante dei sottomenu bisogno di agganciare in qualche modo nello stesso output come il genitore?
Soluzione
Il mio originale render metodo sembrava
public override void Render()
{
var buffer = new StringBuilder();
var extraClass = _hoverState == MenuHoverState.Selected ? "class=\"Selected\"" : "";
// Menu Item Start
buffer.Append("<li><a href=\"" + ComponentParams["link"] + "\"" + extraClass + ">");
// Menu Text
buffer.Append(ComponentParams["title"]);
// Menu Item End
buffer.Append("</a></li>");
RenderText(buffer.ToString());
}
mi serviva per agganciare in Context.Writer:
public override void Render()
{
var buffer = new StringBuilder();
var extraClass = _hoverState == MenuHoverState.Selected ? "class=\"Selected\"" : "";
// Menu Item Start
buffer.Append("<li><a href=\"" + ComponentParams["link"] + "\"" + extraClass + ">");
// Menu Text
buffer.Append(ComponentParams["title"]);
// Menu Item End
buffer.Append("</a><ul class=\"subMenu\" style=\"display:none;\">");
Context.Writer(buffer.ToString());
Context.RenderBody(Context.Writer);
Contet.Writer("</ul></li>");
}
Altri suggerimenti
posso usare Context.RenderBody () per rendere il nidificato ViewComponent derivitives
nel metodo Render override, si potrebbe usare qualcosa come
RenderView("header");
RenderBody();
RenderView("footer");
e magari utilizzare RenderSection potrebbe essere utile per essere in grado di sostituire alcune parti dal modello si utilizza il componente
if(HasSection("header")){
RenderSection("header");
} else {
RenderView("header");
}
è anche possibile itterate e alterare il contesto:
for(var item in this.SubItems){
PropertyBag["item"] = item;
if(HasSection("item")){
RenderSection("item");
} else {
RenderView("item");
}
}
tutte queste soluzioni sono di fantasia, ma io Generaly preferisco avere un viewcomponent che prende uno scopo specifico ViewModel (dire HierarchicalMenuViewModel) come parametro e mantenere la semplice logica di template, è più facile da usare, e la personalizzazione di uscita accadere
almeno per semplici controlli (che sarebbe talvolta meritano soltanto una macro o parziale a seconda del viewengine).
Alla fine, i concetti viewcomponent illustrato sopra sono comunque bello avere quando si fa il controllo che hanno bisogno di più di personalizzazione. Un consiglio è di prendersi cura di documentare la logica di rendering o mantenere le cose semplici (<= 10 linee in render metodo)