重写表单字段呈现逻辑,添加编辑权限控制----这是这个方案实现的核心了。
wss有一套模板的机制,系统的一些控件,包括一些webpart,如果UI比较复杂,都会采用模板来实现,详细请参考:
WSS3.0开发--页面定制(1)--修改列表的表单页面
列表的表单页面,包括查看dispform.aspx,editform.aspx,newform.aspx都采用了一个模板:ListForm,
这个模板嵌入了一个控件--Microsoft.SharePoint.WebControls.ListFieldIterator,这个控件枚举列表的所有字段,生成编辑页面。
那么我们的工作核心就是重写这个ListFieldIterator控件。
通过Reflector查看ListFieldIterator的代码,幸运的是,它不是internal的,那么我们可以继承这个控件实现新的逻辑。不过不幸得是,
ListFieldIterator内部引用了TemplateContainer控件,这个控件的某些
重要属性是internal的,我们的代码没法直接设置,
不过我们还有一招:采用反射。
下面是ListFieldIterator原始的CreateControl方法代码:
[SharePointPermission(SecurityAction.Demand, ObjectModel
=
true
)]
protected
override
void
CreateChildControls()
{
this.Controls.Clear();
if (this.ControlTemplate == null)
{
throw new ArgumentException("Could not find ListFieldIterator control template.");
}
for (int i = 0; i < base.Fields.Count; i++)
{
SPField field = base.Fields[i];
if (!this.IsFieldExcluded(field))
{
TemplateContainer child = new TemplateContainer();
this.Controls.Add(child);
child.ControlMode = base.ControlMode;
child.FieldName = field.InternalName;
this.ControlTemplate.InstantiateIn(child);
}
}
}
下面是重写后的ListFieldIterator:
EditControlListFieldIterator
public class EditControlListFieldIterator : Microsoft.SharePoint.WebControls.ListFieldIterator
{
protected override void CreateChildControls()
{
//只处理编辑模式
if (this.ControlMode != SPControlMode.Edit)
{
base.CreateChildControls();
return;
}
SPUser currentUser = SPContext.Current.Web.CurrentUser ;
//站点管理员可以编辑所有字段
if (currentUser.IsSiteAdmin)
{
base.CreateChildControls();
return;
}
//获取权限配置信息
ListFieldEditSetting listSetting = ListFieldEditSetting.GetListSetting( this.ListId ) ;
if( listSetting == null || listSetting.Count == 0 )
{
base.CreateChildControls();
return ;
}
//base.CreateChildControls();
this.Controls.Clear();
if (this.ControlTemplate == null)
{
throw new ArgumentException("Could not find ListFieldIterator control template.");
}
SPFieldUserValue authorFieldValue = new SPFieldUserValue ( SPContext.Current.Web , ""+ this.ListItem["Author"] ) ;
SPUser author = authorFieldValue.User;
Type t = typeof(TemplateContainer);
//反射获取TemplateContainer的ControlMode属性
PropertyInfo ControlModeProp = t.GetProperty("ControlMode", BindingFlags.Instance | BindingFlags.NonPublic);
PropertyInfo FieldNameProp = t.GetProperty("FieldName", BindingFlags.Instance | BindingFlags.NonPublic);
for (int i = 0; i < base.Fields.Count; i++)
{
SPField field = base.Fields[i];
if (!this.IsFieldExcluded(field))
{
TemplateContainer child = new TemplateContainer();
this.Controls.Add(child);
FieldEditSetting set = listSetting.GetByFieldName(field.InternalName);
if (set != null && !set.CanEdit(currentUser, author))
{
//child.ControlMode = base.ControlMode;
//child.FieldName = field.InternalName;
//ControlModeProp.SetValue(child, this.ControlMode,null);
ControlModeProp.SetValue(child, SPControlMode.Display, null);
}
FieldNameProp.SetValue(child, field.InternalName, null);
this.ControlTemplate.InstantiateIn(child);
}
}
}
}
对比以上两个类的CreateControl方法,相信大家应该了解这个解决方案的核心了。
然后,编写新的模板文件:
CodeArt_Templates.ascx
<%@ Control Language="C#" AutoEventWireup="false" %>
<%@Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.WebControls"%>
<%@Register TagPrefix="SPHttpUtility" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.Utilities"%>
<%@ Register TagPrefix="wssuc" TagName="ToolBar" src="~/_controltemplates/ToolBar.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="ToolBarButton" src="~/_controltemplates/ToolBarButton.ascx" %>
<%@ Register Assembly="CodeArt.SharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2c606279787b575f" Namespace="CodeArt.SharePoint.WebPart" TagPrefix="codeArt" %>
<SharePoint:RenderingTemplate ID="ListForm" runat="server">
<Template>
<SPAN id='part1'>
<SharePoint:InformationBar runat="server"/>
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server">
<Template_RightButtons>
<SharePoint:NextPageButton runat="server"/>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
<SharePoint:FormToolBar runat="server"/>
<TABLE class="ms-formtable" style="margin-top: 8px;" border=0 cellpadding=0 cellspacing=0 width=100%>
<SharePoint:ChangeContentType runat="server"/>
<SharePoint:FolderFormFields runat="server"/>
<codeArt:EditControlListFieldIterator runat="server"/>
<SharePoint:ApprovalStatus runat="server"/>
<SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/>
</TABLE>
<table cellpadding=0 cellspacing=0 width=100%><tr><td class="ms-formline"><IMG SRC="/_layouts/images/blank.gif" width=1 height=1 alt=""></td></tr></table>
<TABLE cellpadding=0 cellspacing=0 width=100% style="padding-top: 7px"><tr><td width=100%>
<SharePoint:ItemHiddenVersion runat="server"/>
<SharePoint:ParentInformationField runat="server"/>
<SharePoint:InitContentType runat="server"/>
<wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator=" " runat="server">
<Template_Buttons>
<SharePoint:CreatedModifiedInfo runat="server"/>
</Template_Buttons>
<Template_RightButtons>
<SharePoint:SaveButton runat="server"/>
<SharePoint:GoBackButton runat="server"/>
</Template_RightButtons>
</wssuc:ToolBar>
</td></tr></TABLE>
</SPAN>
<SharePoint:AttachmentUpload runat="server"/>
<hr/>
</Template>
</SharePoint:RenderingTemplate>
<SharePoint:RenderingTemplate ID="FileFormFields" runat="server">
<Template>
<codeArt:EditControlListFieldIterator runat="server"/>
</Template>
</SharePoint:RenderingTemplate>
OK,我们已经给系统“所有”表单添加了了新的呈现逻辑--只有编辑权限的用户才能可以看到编辑控件。
本系列的所有文章:
CodeArt WSS3.0(MOSS)字段编辑权限控制解决方案(v1.0)
CodeArt WSS3.0(MOSS)字段编辑权限控制解决方案的实现 -- 概要
MOSS字段编辑权限控制方案的实现(1)-管理页面的开发和配置信息的持久化
WSS页面定制系列(2)---定制单个列表的表单页面
WSS页面定制系列(3)---重写表单的保存逻辑
MOSS字段编辑权限控制方案(4)-打包解决方案