WebPart中使用Nvelocity模板引擎来进行呈现
通过使用它,我们可以达到界面与数据的完成分离(当然需要一些设计手段来支持)。
我在公司里的工作主要就是在office sharepoint2007的基础上进行一些类型信息系统的门户站点开发。
而我所在的组开发出了一套通用的组件库,比如类似163新闻的列表新闻部件、FLASH新闻部件等webpart.
目的就在于每建设一个网站时,可以使用这些通用的组件库来进行快速的开发,甚至于我们只需要拖拉+设计css样式就可以完成一个站点的开发。
但是,在不断的开发新网站过程中,发现虽然通过更改css样式可以达到控制webpart的呈现样式。但是,还是有些需求是无法通过更改css来实现的。
当然,这仅仅是对需求的不满足,而我引入模板引擎的另一个想法是:
在指定的目录下,针对每一个webpart都创建它的相应文件夹,在这个文件夹下可以放置多个模板及一个描述模板信息的xml文件。
这样,在页面上使用webpart的时候,我们就可以遍历这个模板文件夹,并读取模板信息,以供选择。
也就是说,我们可以通过这种方式来实现类似webpart换肤的功能(采用模板达到的功能肯定比换肤更强大了)。
如果我们将模板文件夹建到_layouts目录下,甚至还可以达到多个站点共用一套webpart模板。
--------------------------
针对这个设想,我对webpart应用nvelocity进行了简单的测试:
Step1:创建webpart,并在其中输出相关数据<需要引用NVelocity.dll,并using 相关的命名空间>
1 [Guid( " 09a3886f-ccb9-44ed-8838-82969522c37b " )]
2 public class NVelocityTestPart : System.Web.UI.WebControls.WebParts.WebPart,ICallbackEventHandler
3 {
4 public NVelocityTestPart()
5 {
6 this .ExportMode = WebPartExportMode.All;
7 this .ChromeType = PartChromeType.None;
8 }
9 // 可以写个EditorPart,用于从指定的文件夹中循环列出模板文件,让使用者选择
10 // 并且创建一个对应的xml文件,用于给模板添加描述信息等。
11 private string vmPath = " NvelocityDir " ;
12 [
13 WebBrowsable( true ),
14 WebDescription( " 模板文件夹路径 " ),
15 WebDisplayName( " 模板文件夹路径 " ),
16 Personalizable( true )
17 ]
18 public string VmPath
19 {
20 get { return vmPath; }
21 set { vmPath = value; }
22 }
23 private string OutputAjaxFunction()
24 {
25 System.Text.StringBuilder sb = new System.Text.StringBuilder();
26 sb.Append( " <script type=/ " text / javascript/ " language=/ " javascript/ " > " );
27 sb.Append( " /r/n function callServer(cName)/r/n { " );
28 sb.Append( this .Page.ClientScript.GetCallbackEventReference( this , " cName " , " callbackHandler " , "" ) + " ; " );
29 sb.Append( " /r/n } " );
30 sb.Append( " /r/n </script> " );
31 return sb.ToString();
32 }
33 public string CallbackHandle()
34 {
35 System.Text.StringBuilder sb = new System.Text.StringBuilder();
36 sb.Append( " <script type=/ " text / javascript/ " language=/ " javascript/ " > " );
37 sb.Append( " function callbackHandler(rResult) " );
38 sb.Append( " { " );
39 sb.Append( " document.getElementById(‘callbackContainer‘).innerText=rResult; " );
40 sb.Append( " } " );
41 sb.Append( " </script> " );
42 return sb.ToString();
43 }
44 protected override void OnInit(EventArgs e)
45 {
46 // base.OnInit(e);
47 this .Page.ClientScript.RegisterStartupScript( this .GetType(), " AjaxFunc " , OutputAjaxFunction());
48 }
49 protected override void RenderContents(HtmlTextWriter writer)
50 {
51 base .RenderContents(writer);
52 if ( ! System.IO.Directory.Exists( this .Page.Server.MapPath(vmPath)))
53 {
54 writer.Write( " 模板文件夹不存在! " );
55 return ;
56 }
57 try
58 {
59 Author a = new Author();
60 a.Name = " xu zhi ze " ;
61 a.Age = 24 ;
62 Author a1 = new Author();
63 a1.Name = " McJeremy " ;
64 a1.Age = 25 ;
65 System.Collections.Generic.List < Author > us = new System.Collections.Generic.List < Author > ();
66 us.Add(a);
67 us.Add(a1);
68
69 VelocityEngine vEngine = new VelocityEngine();
70 ExtendedProperties props = new ExtendedProperties();
71 props.AddProperty(RuntimeConstants.RESOURCE_LOADER, " file " );
72 //props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, System.IO.Path.GetDirectoryName(this.Page.Request.PhysicalPath));
73 props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, this .Page.Server.MapPath( this .vmPath));
74 props.AddProperty(RuntimeConstants.INPUT_ENCODING, " gb2312 " );
75 props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, " gb2312 " );
76 vEngine.Init(props);
77
78 Template tmp = vEngine.GetTemplate( " default.vm " );
79
80 IContext vContext = new VelocityContext();
81 vContext.Put( " Version " , " 1.0.0.0 " );
82 vContext.Put( " Author " , a);
83 vContext.Put( " Users " , us);
84 vContext.Put( " Instance " , this );
85
86 System.IO.StringWriter sw = new System.IO.StringWriter();
87 tmp.Merge(vContext, sw);
88
89 writer.Write(sw.ToString());
90 }
91 catch (System.Exception ex)
92 {
93 writer.Write(ex.Message);
94 }
95
96 }
97
#region ICallbackEventHandler 成员
99 string rResult = string .Empty;
100 string ICallbackEventHandler.GetCallbackResult()
101 {
102 return rResult;
103 }
104 void ICallbackEventHandler.RaiseCallbackEvent( string eventArgument)
105 {
106 if ( string .IsNullOrEmpty(eventArgument))
107 rResult = " 调用ajax时,传递的值为空! " ;
108 else
109 rResult = " 调用ajax时,传递的值为: " + eventArgument;
110 }
111 #endregion
112 }
Step2:创建模板文件 default.vm,并写呈现逻辑:
1 < pre >
2 /********************************
3 /* A Test of NVelocity in WebPart
4 /* www.cnblogs.com/mcjeremy
5 /********************************
6
7 < h1 > This is a test! </ h1 >
8 Version: ${Version}
9 Author : ${Author.Name}
10 Age : ${Author.Age}
11
12
13 < h3 > NVelocity Test </ h3 >
14
15 Version: $!Version
16 Author : $Author.Name
17 Age : $Author.Age
18
19 #set($company="Mcjeremy‘company")
20 Copyright By < span style ="color:red;" > ${company} </ span >
21
22
23 Users Are:
24 #set($userNum=1)
25 #foreach($user in $Users)
26 < div style ="margin:0px;padding:0px;border:1px dashed blue;width:200px;font-size:14px;font-weight:bold;" >
27 User $userNum
28 Name: $user.Name
29 Age: $user.Age
30 #set($userNum=$userNum+1)
31 </ div >
32 #end
33
34 < h3 > 异步测试 </ h3 >
35 <!-- $Instance -->
36 $Instance.CallbackHandle()
37 < span style ="cursor:pointer;color:red;" onclick ="callServer(‘xu zhi ze‘)" > 点击我 </ span >
38 < div id ="callbackContainer" style ="border:1px dotted silver;width:300px;height:50px;" ></ div >
39 </ pre >
Step3:查看的运行效果如下:
很显然,在webpart中使用nvelocity是可行的,而且非常简单。
接下来要做的事就是
1、实现在一个目录下放置多个模板文件,
2、编写xml文件来描述这些模板,
3、编写一个editorpart来读取这个目录下的模板描述xml,并生成模板的列表,以供使用者选择。
---
目前只测试了在webpart中使用nvelocity。没有进行模板选择的测试。
实际上,模板选择的工作难点在于写editorpart时的xml读取和分析(实际上,这也并不难,毕竟是基础知识的运用而已)
有了使用nvelocity的方法,再加上模板选择的功能应该就容易多了。
原理很简单:在EditorPart中指定WebPart模板所在的文件夹(相对路径),并通过输入的文件夹路径获取该文件夹下的templates.xml(即模板描述文件)。
然后列出该模板描述文件中的模板列表供选择。模板描述文件格式及内容如下(如果要在项目中应用,可能还需要作相应的更改):
1 <? xml version="1.0" encoding="utf-8" standalone="yes" ?>
2 < TemplateFiles >
3 < TemplateFile >
4 < FileName >
5 <![CDATA[ default.vm ]]>
6 </ FileName >
7 < TemplateName > 默认 </ TemplateName >
8 < Description > 描述111111 </ Description >
9 < Author > pcitxzz </ Author >
10 < CreateDate > 2009-08-18 </ CreateDate >
11 </ TemplateFile >
12 < TemplateFile >
13 < FileName > <![CDATA[ new2.vm ]]> </ FileName > <!-- 文件名 -->
14 < TemplateName > 新的 </ TemplateName > <!-- 模板名 -->
15 < Description > 描述2222 </ Description > <!-- 模板描述 -->
16 < Author > pcitxzz </ Author > <!-- 创建者 -->
17 < CreateDate > 2009-08-18 </ CreateDate > <!-- 创建日期 -->
18 </ TemplateFile >
19 </ TemplateFiles >
在编写EditorPart时,读取这个xml文件并分析即可。
完成EditorPart的编写后,就可以在webpart中进行应用了。
------------------------------------------
以下是我测试的相关截图:
No1:EditorPart中选择模板的效果:
No2:使用默认模板时的效果:
No3:使用“新的”模板时的效果:
可以看出,通过这种方式为同一个webpart应用不同的模板十分方便。
尤其是在实现CSS样式无法实现的布局时或需要一些特殊功能时,您可以考虑这种实现方式。
----
相关源码:/Files/McJeremy/NVelocityTestPart.rar
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。