通过使用它,我们可以达到界面与数据的完成分离(当然需要一些设计手段来支持)。
我在公司里的工作主要就是在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