现在的位置: 首页 > 综合 > 正文

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

2014年11月12日 ⁄ 综合 ⁄ 共 7713字 ⁄ 字号 评论关闭
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

----
转载请注明出处:http://www.cnblogs.com/mcjeremy

抱歉!评论已关闭.