Castle NVelocity - 1.1

VTL语法
注释
单行注释以##开始,多行注释以#*开始,以*#结束。注释的内容不会出现在输出中

属性

属性引用以$符号开始。属性可以是服务器端C#代码设置的,也可以在NVelocity模板中定义属性,比如下面语句在NVelocity模板中定义一个属性
#set (#msg="this variable is defined in NVelocity.")
NVelocity中定义的属性一般为字符串值,赋值时可以使用单引号将字符串值括起来,也可以使用双引号,他们的区别是:如果字符串值中有用到其他变量,使用单引号时该变量名字直接作为字符串的值处理,而使用双引号时该变量名字将使用属性的值进行替换(可以设置NVelocity关闭这个选项)
在模板中如果需要输出以$符号开始的文本(非变量),有2种处理方式。如果他不会作为属性赋值,则可以直接输出,因为NVelocity对没有赋值的属性,直接输出属性名字(包括$符号);如果他是一个已经赋值的属性,则需要在$符号前面添加一个转义用的反斜杠\符号
对于非字符串类型的属性,NVelocity调用属性的ToString()方法转换为字符串输出
对于对象类型的属性,可以使用类似$contact.Name方式,NVelocity目前的版本已经支持属性名称非大小写敏感

控制指令
条件指令:
NVelocity中的控制指令基本上就2个:条件指令和循环指令。NVelocity对宏的支持不太好
#if($score>1000) Expert #elseif($score>500) Senior #else Junior #endif
与Velocity不一样的地方:NVelocity不支持#{else}这个语法,#else、#endif指令必须与前后的内容空格分开

循环指令:
NVelocity的循环指令,每个指令必须单独占用一行,不能有注释、输出内容等
NVelocity对Velocity的循环指令做了扩展,加入了 Fog Creek的Fancy Loops
基本语法如下:
#foreach($i in $items)
#each 
    (this is optional since its the default section)
    text which appears for each item
#before
    text which appears before each item
#after
    text which appears after each item
#between
    text which appears between each two items
#odd
    text which appears for every other item, including the first
#even
    text which appears for every other item, starting with the second
#nodata
    Content rendered if $items evaluated to null or empty
#beforeall
    text which appears before the loop, only if there are items
    matching condition
#afterall
    text which appears after the loop, only of there are items
    matching condition
#end
Fancy Loops指令非常实用,例如在StringTemplate中想要类似的效果就比较麻烦

其他还有#include、#parse、#stop指令,详细的语法参考 VTL Reference  

基本用法
下载Castle NVelocity项目,建一个测试用的web site,引用NVelocity.dll,引用的命名空间如下:
using System;
using System.Collections.Generic;
using System.Data;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using NVelocity.Runtime;
建立一个NVelocity模板,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
< div  class="query-form">
     < table >
         < tr >
             < td >姓名:</ td >
             < td >< input  type="text" id="txtQryName" class="text" value="$qryName" /></ td >
             < td >地址:</ td >
             < td >< input  type="text" id="txtQryAddress" class="text" value="$qryAddress" /></ td >
             < td >< input  type="button" id="btnQuery" value="查询" /></ td >
         </ tr >
     </ table >
</ div >
< br >
< h2 >Contact List</ h2 >
< div  class="contact-list">
#foreach($c in $contacts)
#beforeall
     < table >
         < tr  class="list-header">
             < td >姓名</ td >
             < td >邮箱</ td >
             < td >地址</ td >
             < td >会员等级</ td >
         </ tr >
#odd
         < tr  class="list-odd">
#even
         < tr  class="list-even">
#each
             < td >$c.set_Name("$c.name - W") $c.get_Name()</ td >
             < td >< a  href="mailto:$c.EMail">$c.EMail</ a ></ td >
             < td >$c.Address</ td >
             < td >#if($c.TotalOrderAmt>1000)钻卡会员
     #elseif($c.TotalOrderAmt>200)金卡会员
     #else Standard#end</ td >
#after
         </ tr >
#afterall
     </ table >
#nodata
     No contacts found!
#end
</ div >
页面.cs代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public  class  Contact
{
     public  string  Name { get ; set ; }
     public  string  EMail { get ; set ; }
     public  string  Address { get ; set ; }
     public  decimal  TotalOrderAmt { get ; set ; }
}
<br>
protected  void  Page_Load( object  sender, EventArgs e)
{
     VelocityEngine engine = new  VelocityEngine();
     ExtendedProperties prop = new  ExtendedProperties();
     prop.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Server.MapPath( "./" ));
     prop.AddProperty(RuntimeConstants.ENCODING_DEFAULT, "utf-8" );
     engine.Init(prop);
     Template template = engine.GetTemplate( "contact-list.vm" );
     VelocityContext context = new  VelocityContext();
     context.Put( "contacts" , new  List<Contact>()
     {
         new  Contact() {
             Name= "Richie Liu" , TotalOrderAmt=180,
             EMail= "[email protected]" ,
             Address= "上海徐汇区钦州路"  },
         new  Contact() {
             Name= "Kevin Zhang" ,TotalOrderAmt=0,
             EMail= "[email protected]" ,
             Address= "苏州新区"  },
         new  Contact() {
             Name= "Eric Wong" , TotalOrderAmt=626,
             EMail= "[email protected]" ,
             Address= "厦门海沧"  },
         new  Contact() {
             Name= "RicCC" , TotalOrderAmt=2080,
             EMail= "[email protected]" ,
             Address= "上海徐汇区钦州路"  }
     });
     context.Put( "qryName" , "Ric" );
     context.Put( "qryAddress" , DateTime.Now);
<br>
     template.Merge(context, this .Response.Output);
}
则页面运行结果:
     Castle NVelocity - 1.1_第1张图片
上面的代码中,演示了在NVelocity模板中调用对象的方法,比如$c.get_Name()通过getter方法读取属性值;$c.set_Name("$c.name - W")为每个contact的名字添加一个-W后缀
如果$contacts集合中没有记录,则只会输出No contacts found!文本,不会输出任何table信息,包括#beforeall、#afterall指令中的内容也不会输出

接下来测试一下#foreach指令能够支持的集合类型以及用法(只要支持IEnumarable接口的都可以使用#foreach指令)
NVelocity模板如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
< br  />
< h2 >Item List - Array</ h2 >
< div >
#foreach($item in $items1)
#each
     $item
#between
     ,
#end
</ div >
< br >
< br  />
< h2 >Item List - List</ h2 >
< div >
#foreach($item in $items2)
#each
     $item.ToString("yyyy-MM-dd")
#between
     ,
#end
</ div >
< br >
< br  />
< h2 >Item List - Dictionary</ h2 >
< div >
#foreach($item in $items3)
#each
{ $item.Key - $item.Value }
#between
,#end
</ div >
< br >
< br  />
< h2 >Item List - DataTable</ h2 >
< div >
#foreach($item in $items4.Rows)
{ $item.Key - $item.Value }
#between
,
#end
</ div >
服务器端设置属性的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
context.Put( "items1" , new  string [] { "AAA" , "BBB" , "CCC"  });
context.Put( "items2" , new  List<DateTime> { new  DateTime(1979, 1, 1), new  DateTime(2010, 4, 1) });
<br>
IDictionary< string , decimal > dic = new  Dictionary< string , decimal >();
dic.Add( "AAA" , 111M);
dic.Add( "BBB" , 222M);
dic.Add( "CCC" , 333M);
context.Put( "items3" , dic);
<br>
DataTable table = new  DataTable();
table.Columns.Add( new  DataColumn( "Key" , typeof ( string )));
table.Columns.Add( new  DataColumn( "Value" , typeof ( int )));
DataRow row = table.NewRow();
row[ "Key" ] = "item 1" ;
row[ "Value" ] = 111;
table.Rows.Add(row);
row = table.NewRow();
row[ "Key" ] = "item 2" ;
row[ "Value" ] = 222;
table.Rows.Add(row);
context.Put( "items4" , table);
页面运行效果如下:
     Castle NVelocity - 1.1_第2张图片

你可能感兴趣的:(Castle NVelocity - 1.1)