在MonoRail中我们可以定义一些可重用的组件,在其他需要使用的页面引入这个组件就可以了。有点相当于.NET中的自定义控件,可以节约代码,方便开发,提高重用性。我们可以用这个组件的方式来封装常用的功能,
1.分页功能
2.编辑器
3....
使用一个ViewComponent(视图组件)
A ViewComponent has no relation with controller, only with the views selected by the controllers.
视图组件和控制器没有关系,仅仅是一个视图,可以被控制器选择
简单嵌入
#component(HeaderComponent)
嵌套使用#blockcomponent(NewsComponent)
<ul>
#foreach($new in $news)
<li>$news.Date $news.Title</li>
#end
</ul>
#end
<ul>
#foreach($new in $news)
<li>$news.Date $news.Title</li>
#end
</ul>
#end
创建一个视图组件(Creating a ViewComponent)
A ViewComponent is a class that extends ViewComponent abstract class. Three methods can be optionally overriden to customize its behavior:
Render: selects the view or uses another approach to render the component content
Initialize: used to intialize the state of your view component, usually by examining supplied parameters
SupportsSection: invoked by the view engine to check if the component supports the section supplied on the view
Note that starting with v1RC3, much of the work normally handled in the Initialize and SupportsSection methods is now done using attributes, so it should be rare to need those methods.
要创建ViewComponet就要继承ViewComponent 类,有三个方法可以被覆盖
Initialize:初始化,可以在这个方法中接收传递的参数
Render:渲染实际的显示内容
SupportsSection:指定这个组件可以支持哪些子节点
首先创建一个简单的ViewComponent
using Castle.MonoRail.Framework;
public class HeaderComponent : ViewComponent
{
}
当使用这个组件时会直接渲染views下的components/headercomponent/default.vm文件public class HeaderComponent : ViewComponent
{
}
当然和Controller一样,我们也可以指定一个渲染的vm文件:
using Castle.MonoRail.Framework;
public class HeaderComponent : ViewComponent
{
public override void Render()
{
RenderView("otherview");
}
}
定义一个带参数的ViewComponentpublic class HeaderComponent : ViewComponent
{
public override void Render()
{
RenderView("otherview");
}
}
public class StatsComponent : ViewComponent
{
private static Random rnd = new Random();
private string pageName;
[ViewComponentParam]
public string PageName
{
get { return pageName; }
set { pageName = value; }
}
public override void Render()
{
PropertyBag["pagename"] = pageName;
// Pretend to obtain access count
PropertyBag["accessCount"] = rnd.Next(1, Int16.MaxValue);
base.Render();
}
}
{
private static Random rnd = new Random();
private string pageName;
[ViewComponentParam]
public string PageName
{
get { return pageName; }
set { pageName = value; }
}
public override void Render()
{
PropertyBag["pagename"] = pageName;
// Pretend to obtain access count
PropertyBag["accessCount"] = rnd.Next(1, Int16.MaxValue);
base.Render();
}
}
其中PageName就是一个ViewComponet的参数
我们可以这样来使用
#component(StatsComponent with "pagename='home/index'")
那么再来一个复杂点的例子:
public class TableComponent : ViewComponent
{
private ICollection elements;
private object border;
private string style;
private object cellpadding;
private object cellspacing;
[ViewComponentParam(Required = true)]
public ICollection Elements
{
get { return elements; }
set { elements = value; }
}
[ViewComponentParam]
public object Border
{
get { return border; }
set { border = value; }
}
[ViewComponentParam]
public string Style
{
get { return style; }
set { style = value; }
}
[ViewComponentParam]
public object Cellpadding
{
get { return cellpadding; }
set { cellpadding = value; }
}
[ViewComponentParam]
public object Cellspacing
{
get { return cellspacing; }
set { cellspacing = value; }
}
// Another approach to read parameters:
// public override void Initialize()
// {
// elements = (ICollection) ComponentParams["elements"];
//
// border = ComponentParams["border"];
// style = (String) ComponentParams["style"];
// cellpadding = ComponentParams["cellpadding"];
// cellspacing = ComponentParams["cellspacing"];
//
// base.Initialize();
// }
public override void Render()
{
RenderText(
String.Format("<table border=\"{0}\" style=\"{1}\" cellpadding=\"{2}\" cellspacing=\"{3}\">",
border, style, cellpadding, cellspacing));
if (Context.HasSection("colheaders"))
{
Context.RenderSection("colheaders");
}
if (elements != null)
{
int index = 0;
foreach(object item in elements)
{
PropertyBag["index"] = ++index;
PropertyBag["item"] = item;
if (Context.HasSection("altitem") && index % 2 != 0)
{
Context.RenderSection("altitem");
}
else
{
Context.RenderSection("item");
}
}
}
RenderText("</table>");
}
public override bool SupportsSection(string name)
{
return name == "colheaders" || name == "item" || name == "altitem";
}
}
我们在控制器中对items赋值数组{
private ICollection elements;
private object border;
private string style;
private object cellpadding;
private object cellspacing;
[ViewComponentParam(Required = true)]
public ICollection Elements
{
get { return elements; }
set { elements = value; }
}
[ViewComponentParam]
public object Border
{
get { return border; }
set { border = value; }
}
[ViewComponentParam]
public string Style
{
get { return style; }
set { style = value; }
}
[ViewComponentParam]
public object Cellpadding
{
get { return cellpadding; }
set { cellpadding = value; }
}
[ViewComponentParam]
public object Cellspacing
{
get { return cellspacing; }
set { cellspacing = value; }
}
// Another approach to read parameters:
// public override void Initialize()
// {
// elements = (ICollection) ComponentParams["elements"];
//
// border = ComponentParams["border"];
// style = (String) ComponentParams["style"];
// cellpadding = ComponentParams["cellpadding"];
// cellspacing = ComponentParams["cellspacing"];
//
// base.Initialize();
// }
public override void Render()
{
RenderText(
String.Format("<table border=\"{0}\" style=\"{1}\" cellpadding=\"{2}\" cellspacing=\"{3}\">",
border, style, cellpadding, cellspacing));
if (Context.HasSection("colheaders"))
{
Context.RenderSection("colheaders");
}
if (elements != null)
{
int index = 0;
foreach(object item in elements)
{
PropertyBag["index"] = ++index;
PropertyBag["item"] = item;
if (Context.HasSection("altitem") && index % 2 != 0)
{
Context.RenderSection("altitem");
}
else
{
Context.RenderSection("item");
}
}
}
RenderText("</table>");
}
public override bool SupportsSection(string name)
{
return name == "colheaders" || name == "item" || name == "altitem";
}
}
然后我们可以这样来调用 (数据源,表格线粗,样式,内,间的宽度)里面还包含 colheaders头,item项目模板,altitem间隔模板.
#blockcomponent(TableComponent with "elements=$items" "border=0" "style=border: 1px solid black;" "cellpadding=0" "cellspacing=2")
#colheaders
<tr>
<th> </th>
<th>Element</th>
</tr>
#end
#item
<tr>
<td align="center">$index</td>
<td>$item</td>
</tr>
#end
#altitem
<tr style="background: #c0c0c0;">
<td align="center">$index</td>
<td>$item</td>
</tr>
#end
#end
#colheaders
<tr>
<th> </th>
<th>Element</th>
</tr>
#end
#item
<tr>
<td align="center">$index</td>
<td>$item</td>
</tr>
#end
#altitem
<tr style="background: #c0c0c0;">
<td align="center">$index</td>
<td>$item</td>
</tr>
#end
#end