因为最近一个项目需要使用Webpart技术, 对于这个.net2.0时代的事物, 我算是个后进生, 所以只得临时抱佛脚.遇到了一些问题,顺道总结一下.
1. 自定义个性化Provider: 继承PersonalizationProvider类,重载其中的关键虚方法即可. 很多文章讲述到这个,不在累述.
2. 自定义的目录列表: 我想实现的效果是, 在webpart的目录视图中, 可以从数据库中动态的加载一个用户可供使用的webpart组件列表.
这个时候, 我们需要继承System.Web.UI.WebControls.WebParts.CatalogPart类,重载其中的GetAvailableWebPartDescriptions()和GetWebPart(WebPartDescription description)方法.类似如下代码:

Code
public override WebPartDescriptionCollection GetAvailableWebPartDescriptions(){
IList<Module> modules = FindModules();
List<WebPartDescription> list = new List<WebPartDescription>();
foreach (Module m in modules)
{
WebPartDescription wpd = new WebPartDescription(m.ID, m.Name, m.Description, "");
list.Add(wpd);
}
WebPartDescriptionCollection wpdc = new WebPartDescriptionCollection(list);
return wpdc;
}
public override WebPart GetWebPart(WebPartDescription description){
string id = description.ID;
Module module = ModuleSrv.FindModule(id);
//这里要使用Page的LoadControl方法, Control的Load方法会造成很多问题.
Control ctl = Page.LoadControl(CommonWebpartUrl);
// WebPartBase是自己实现的Webpart用户控件的一个基类
WebPartBase baseCtl = ctl as WebPartBase;
baseCtl.ID = id;
//将用户控件包装起来
GenericWebPart gwp = WebPartManager.CreateWebPart(ctl);
//这个AuthorizationFilter是用于以后验证Webpart的权限的用途
gwp.AuthorizationFilter = module.ID;
return gwp;
}
在页面上使用时放入CatalogZone中.另外DeclarativeCatalogPart中的属性WebPartsListUserControlPath也很好用, 可以指向一个用户控件, 这个用户控件页面中包含几个Webpart组件, 目录的列表中就有几个, 也算是比较动态了.

Code
<asp:CatalogZone ID="CatalogZone1" runat="server">
<ZoneTemplate>
<cc1:WorkbenchCatalogPart ID="WorkbenchCatalogPart1" runat="server" Title="可用的功能"/>
</ZoneTemplate>
</asp:CatalogZone>
3. 不让用户在界面上重复的添加同一个Webpart控件: WebPartManager控件有个OnWebPartAdding, 在组件被添加到界面前触发, 利用这个机会,就可以进行判断.

Code
protected void WebPartManager1_WebPartAdding(object sender, WebPartAddingEventArgs e){
foreach (WebPart part in WebPartManager1.WebParts){
WebPartBase baseCtl = part.Controls[0] as WebPartBase;
if (e.WebPart 是 part){
e.Cancel = true;
break;
}
}
}
4. 只有用户拥有权限的Webpart才在界面上显示出来. WebPartManager类在加载每个Webpart组件时都有一个onauthorizewebpart事件, 在事件中判断用户对这个Webpart的权限, 这样即便是这个组件在共享视图中, 没有权限也不会显示出来.

Code
protected void WebPartManager1_AuthorizeWebPart(object sender, WebPartAuthorizationEventArgs e)
{ // AuthorizationFilter成为判断权限的关键信息.
e.IsAuthorized = GetPermission(e.AuthorizationFilter);
}