如何在Monorail和Nvelocity中创建嵌套的视图组件?
-
03-10-2019 - |
题
我被要求更新我们维护的网站上的菜单。该网站使用Castle Windors Monorail和Nvelocity作为模板。目前,使用自定义的ViewComponent的子类渲染菜单,该子类呈现LI元素。目前,只有一个(水平)水平,因此当前机制很好。
我被要求将菜单添加到一些现有菜单中。因为这是我第一次看到单轨和nvelocity,所以我有点迷路了。
目前存在的内容:
<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>
是否可以使用嵌套的薄膜组件(或新的子元素)类似:
<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>
我需要在Menucomponent上的覆盖渲染方法中绘制子菜单(UL和LI元素),因此使用嵌套的ViewComponent衍生物可能不起作用。我希望一种方法可以保留基本的声明性方法来创建菜单,如果可能的话。
编辑:我可以使用context.renderbody()渲染嵌套的ViewComponent衍生物,但它们是在父母面前渲染的。我猜该子菜单需要以某种方式与父母相同的输出挂钩?
解决方案
我原来的渲染方法看起来像
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());
}
我需要挂在上下文中。作者:
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>");
}
其他提示
我可以使用context.renderbody()渲染嵌套的查看组件衍生物
在您的渲染方法中,您可以使用类似的东西
RenderView("header");
RenderBody();
RenderView("footer");
也许使用呈现可能会很有用,因为能够从模板中覆盖某些零件您使用组件
if(HasSection("header")){
RenderSection("header");
} else {
RenderView("header");
}
也可能会迭代并改变上下文:
for(var item in this.SubItems){
PropertyBag["item"] = item;
if(HasSection("item")){
RenderSection("item");
} else {
RenderView("item");
}
}
所有这些解决方案都是花哨的,但是我一般更喜欢拥有一个视图组件,该视图组件以特定目的的视图模型(例如erarchicalMenuviewModel)作为一个参数,并使模板逻辑保持简单,更易于使用,并且输出自定义发生了。
至少对于简单的控件(有时候只能根据ViewEngine获得宏观或部分)。
最后,在执行需要更多自定义的控制时,上面说明的视图组件概念仍然很不错。一个建议是照顾记录渲染逻辑或保持简单(<=渲染方法中的10行)