如何在Monorail和NVelocity中创建嵌套的ViewComponents?

时间:2010-05-05 22:23:32

标签: castle-monorail nvelocity

我被要求更新我们维护的网站上的菜单。该网站使用Castle Windors Monorail和NVelocity作为模板。该菜单当前使用ViewComponent的自定义子类进行渲染,该子类渲染li元素。目前只有一个(水平)水平,所以目前的机制很好。

我被要求在一些现有菜单中添加下拉菜单。因为这是我第一次看到Monorail和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>

是否可以使用嵌套的MenuComponents(或新的SubMenuComponent):

<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派生词,但它们在父目录之前呈现。我想子菜单的rending需要以某种方式挂钩到与父对象相同的输出?

2 个答案:

答案 0 :(得分:0)

我的原始渲染方法看起来像

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());
}

我需要挂钩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>");    
}

答案 1 :(得分:0)

  

我可以使用Context.RenderBody()来渲染嵌套的ViewComponent派生词

在Render方法覆盖中,您可以使用类似

的内容
RenderView("header");
RenderBody();
RenderView("footer");

并且可能使用RenderSection对于能够覆盖使用组件的模板中的某些部分非常有用

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");
    }
}

所有这些解决方案都很花哨,但我通常更喜欢使用一个viewcomponent,它将一个特定于目的的视图模型(比如HierarchicalMenuViewModel)作为参数,并使模板逻辑保持简单,更容易使用,并且输出定制发生

至少对于简单的控件(根据视图引擎,有时只需要一个宏或部分控件)。

最后,当进行需要更多自定义的控制时,上面说明的viewcomponent概念仍然很好。建议是注意记录渲染逻辑或保持简单(在渲染方法中<= 10行)