WebPart中使用Nvelocity模板引擎来进行呈现

WebPart中使用Nvelocity模板引擎来进行呈现

分类: SharePoint
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 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。