通过上一篇文章
WSS页面定制系列(2)---定制单个列表的表单页面您应该了解到了如何定制列表那些查看,新增,修改的页面。但是只限于页面布局。
如果需要修改保存逻辑应该怎么做呢?
这个需求还是很常见的,比如,保存之前做一些校验,保存之后重定向到某个页面。
系统模板里面负责保存操作的是如下的控件:
如果需要修改保存逻辑应该怎么做呢?
这个需求还是很常见的,比如,保存之前做一些校验,保存之后重定向到某个页面。
系统模板里面负责保存操作的是如下的控件:
<SharePoint:SaveButton runat="server"/>
这个控件位于Microsoft.SharePoint.WebControls名称控件。我们用reflector找到关键代码:
OnBubbleEvent
[SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
protected override bool OnBubbleEvent(object source, EventArgs e)
{
SPListItem listItem;
string redirectUrl;
bool flag = false;
if (e is CommandEventArgs)
{
CommandEventArgs args = (CommandEventArgs) e;
if (!(args.CommandName == "SaveItem"))
{
return flag;
}
listItem = base.ItemContext.ListItem;
if ((listItem != null) && (base.ItemContext.ContentType != null))
{
try
{
listItem["ContentType"] = base.ItemContext.ContentType.Name;
listItem.SetExtraInfo("ContentTypeId", base.ItemContext.ContentType.Id.ToString(), "");
}
catch (ArgumentException)
{
}
}
}
else
{
return flag;
}
this.Page.Validate();
if (this.Page.IsValid)
{
bool flag2 = false;
EventHandler onSaveHandler = base.ItemContext.FormContext.OnSaveHandler;
if (onSaveHandler == null)
{
if (base.List.BaseTemplate != SPListTemplateType.Survey)
{
flag2 = this.SaveItem();
}
else if (base.ItemContext.FormContext.NextFieldName != null)
{
if (base.ControlMode != SPControlMode.New)
{
flag2 = this.SaveItem();
}
else
{
listItem.Checkout();
flag2 = true;
}
}
else
{
listItem.Checkin();
flag2 = true;
}
}
else
{
onSaveHandler(this, EventArgs.Empty);
flag2 = true;
}
flag = true;
if (!flag2)
{
return flag;
}
redirectUrl = base.RedirectUrl;
if (((base.ItemContext.List.BaseTemplate == SPListTemplateType.Events) || ((base.ItemContext.ContentType != null) && base.ItemContext.ContentType.Id.IsChildOf(SPBuiltInContentTypeId.Event))) && base.ItemContext.FormContext.WantRedirectForMWS)
{
if ((base.ItemContext.FormContext.FormMode == SPControlMode.New) && base.ItemContext.FormContext.NeedIDForNewMWS)
{
redirectUrl = redirectUrl + "&Item=" + base.ItemContext.ListItem.ID.ToString(CultureInfo.InvariantCulture);
}
SPUtility.Redirect(redirectUrl, SPRedirectFlags.Default, this.Context);
return flag;
}
}
else
{
return true;
}
if (base.ItemContext.List.BaseTemplate == SPListTemplateType.WebPageLibrary)
{
redirectUrl = ((SPListItem) base.Item).File.ServerRelativeUrl;
}
SPUtility.Redirect(redirectUrl, SPRedirectFlags.UseSource, this.Context);
return flag;
}
[SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
protected override bool OnBubbleEvent(object source, EventArgs e)
{
SPListItem listItem;
string redirectUrl;
bool flag = false;
if (e is CommandEventArgs)
{
CommandEventArgs args = (CommandEventArgs) e;
if (!(args.CommandName == "SaveItem"))
{
return flag;
}
listItem = base.ItemContext.ListItem;
if ((listItem != null) && (base.ItemContext.ContentType != null))
{
try
{
listItem["ContentType"] = base.ItemContext.ContentType.Name;
listItem.SetExtraInfo("ContentTypeId", base.ItemContext.ContentType.Id.ToString(), "");
}
catch (ArgumentException)
{
}
}
}
else
{
return flag;
}
this.Page.Validate();
if (this.Page.IsValid)
{
bool flag2 = false;
EventHandler onSaveHandler = base.ItemContext.FormContext.OnSaveHandler;
if (onSaveHandler == null)
{
if (base.List.BaseTemplate != SPListTemplateType.Survey)
{
flag2 = this.SaveItem();
}
else if (base.ItemContext.FormContext.NextFieldName != null)
{
if (base.ControlMode != SPControlMode.New)
{
flag2 = this.SaveItem();
}
else
{
listItem.Checkout();
flag2 = true;
}
}
else
{
listItem.Checkin();
flag2 = true;
}
}
else
{
onSaveHandler(this, EventArgs.Empty);
flag2 = true;
}
flag = true;
if (!flag2)
{
return flag;
}
redirectUrl = base.RedirectUrl;
if (((base.ItemContext.List.BaseTemplate == SPListTemplateType.Events) || ((base.ItemContext.ContentType != null) && base.ItemContext.ContentType.Id.IsChildOf(SPBuiltInContentTypeId.Event))) && base.ItemContext.FormContext.WantRedirectForMWS)
{
if ((base.ItemContext.FormContext.FormMode == SPControlMode.New) && base.ItemContext.FormContext.NeedIDForNewMWS)
{
redirectUrl = redirectUrl + "&Item=" + base.ItemContext.ListItem.ID.ToString(CultureInfo.InvariantCulture);
}
SPUtility.Redirect(redirectUrl, SPRedirectFlags.Default, this.Context);
return flag;
}
}
else
{
return true;
}
if (base.ItemContext.List.BaseTemplate == SPListTemplateType.WebPageLibrary)
{
redirectUrl = ((SPListItem) base.Item).File.ServerRelativeUrl;
}
SPUtility.Redirect(redirectUrl, SPRedirectFlags.UseSource, this.Context);
return flag;
}
SaveItem
public static bool SaveItem(SPContext itemContext, bool uploadMode, string checkInComment)
{
if (itemContext == null)
{
throw new ArgumentNullException("itemContext");
}
if (checkInComment == null)
{
throw new ArgumentNullException("checkInComment");
}
ActionBeforeSaveItem(itemContext);
if ((itemContext.FormContext != null) && (itemContext.FormContext.FormMode == SPControlMode.New))
{
SPFolder rootFolder = null;
string rootFolderUrl = itemContext.RootFolderUrl;
if ((!string.IsNullOrEmpty(rootFolderUrl) && (itemContext.List != null)) && (itemContext.List.ParentWeb != null))
{
rootFolder = itemContext.List.ParentWeb.GetFolder(rootFolderUrl);
}
if (rootFolder == null)
{
rootFolder = itemContext.List.RootFolder;
}
if (itemContext.FormContext.IsFolder)
{
return CreateFolder(rootFolder, itemContext);
}
}
else if (!uploadMode)
{
if (itemContext.Item == null)
{
throw new InvalidOperationException();
}
try
{
itemContext.Item.Update();
goto Label_01C8;
}
catch (SPException exception)
{
SPList list = itemContext.List;
if ((exception.ErrorCode == -2130575305) && (list != null))
{
while (list.BaseTemplate != SPListTemplateType.WebPageLibrary)
{
if (list.BaseType == SPBaseType.DocumentLibrary)
{
goto Label_00B8;
}
break;
}
throw new SPException(SPResource.GetString("ListVersionMismatch", new object[0]));
}
Label_00B8:
throw;
}
}
else
{
SPListItem item = itemContext.Item as SPListItem;
if (!SPUtility.IsCheckedOut(item))
{
item.UpdateOverwriteVersion();
}
else
{
item.Update();
item.File.CheckIn(checkInComment);
}
goto Label_01C8;
}
if (itemContext.List.BaseType == SPBaseType.DocumentLibrary)
{
throw new InvalidOperationException();
}
if (itemContext.Item == null)
{
throw new InvalidOperationException();
}
itemContext.Item.Update();
Label_01C8:
HandleNonFatalError(itemContext);
return true;
}
public static bool SaveItem(SPContext itemContext, bool uploadMode, string checkInComment)
{
if (itemContext == null)
{
throw new ArgumentNullException("itemContext");
}
if (checkInComment == null)
{
throw new ArgumentNullException("checkInComment");
}
ActionBeforeSaveItem(itemContext);
if ((itemContext.FormContext != null) && (itemContext.FormContext.FormMode == SPControlMode.New))
{
SPFolder rootFolder = null;
string rootFolderUrl = itemContext.RootFolderUrl;
if ((!string.IsNullOrEmpty(rootFolderUrl) && (itemContext.List != null)) && (itemContext.List.ParentWeb != null))
{
rootFolder = itemContext.List.ParentWeb.GetFolder(rootFolderUrl);
}
if (rootFolder == null)
{
rootFolder = itemContext.List.RootFolder;
}
if (itemContext.FormContext.IsFolder)
{
return CreateFolder(rootFolder, itemContext);
}
}
else if (!uploadMode)
{
if (itemContext.Item == null)
{
throw new InvalidOperationException();
}
try
{
itemContext.Item.Update();
goto Label_01C8;
}
catch (SPException exception)
{
SPList list = itemContext.List;
if ((exception.ErrorCode == -2130575305) && (list != null))
{
while (list.BaseTemplate != SPListTemplateType.WebPageLibrary)
{
if (list.BaseType == SPBaseType.DocumentLibrary)
{
goto Label_00B8;
}
break;
}
throw new SPException(SPResource.GetString("ListVersionMismatch", new object[0]));
}
Label_00B8:
throw;
}
}
else
{
SPListItem item = itemContext.Item as SPListItem;
if (!SPUtility.IsCheckedOut(item))
{
item.UpdateOverwriteVersion();
}
else
{
item.Update();
item.File.CheckIn(checkInComment);
}
goto Label_01C8;
}
if (itemContext.List.BaseType == SPBaseType.DocumentLibrary)
{
throw new InvalidOperationException();
}
if (itemContext.Item == null)
{
throw new InvalidOperationException();
}
itemContext.Item.Update();
Label_01C8:
HandleNonFatalError(itemContext);
return true;
}
DefaultTemplateName
protected override string DefaultTemplateName
{
get
{
return "SaveButton";
}
}
protected override string DefaultTemplateName
{
get
{
return "SaveButton";
}
}
SaveButton 控件也是采用模板实现的,它的模板如下 :
<SharePoint:RenderingTemplate ID="SaveButton" runat="server">
<Template> <TABLE cellpadding=0 cellspacing=0 ;<TR><TD align="<SharePoint:EncodedLiteral runat='server' text='<%$Resources:wss,multipages_direction_right_align_value%>' EncodeMethod='HtmlEncode'/>" width=100% nowrap>
<asp:Button UseSubmitBehavior="false" ID=diidIOSaveItem CommandName="SaveItem" Text="<%$Resources:wss,tb_save%>" class="ms-ButtonHeightWidth" accesskey="<%$Resources:wss,tb_save_AK%>" target="_self" runat="server"/>
</TD> </TR> </TABLE>
</Template>
</SharePoint:RenderingTemplate>
<Template> <TABLE cellpadding=0 cellspacing=0 ;<TR><TD align="<SharePoint:EncodedLiteral runat='server' text='<%$Resources:wss,multipages_direction_right_align_value%>' EncodeMethod='HtmlEncode'/>" width=100% nowrap>
<asp:Button UseSubmitBehavior="false" ID=diidIOSaveItem CommandName="SaveItem" Text="<%$Resources:wss,tb_save%>" class="ms-ButtonHeightWidth" accesskey="<%$Resources:wss,tb_save_AK%>" target="_self" runat="server"/>
</TD> </TR> </TABLE>
</Template>
</SharePoint:RenderingTemplate>
这里有一点有趣的东西,SaveButton利用了asp.net里面的事件冒泡机制,即子控件产生事件(就是那个CommandName="SaveItem"
的Button),但并不处理,而是把事件“冒上去”,由父控件进行拦截处理(OnBubbleEvent方法)。
(既然是这样,我们用一个图片按钮来取代那个diidIOSaveItem应该也是可以的,只要ID和CommandName不变。)
言归正传---------------我第一次看到SaveButton控件的核心代码的时候,感到有点晕,太复杂了~ 而且,里面的很多内部方法都是私有的!
怎么改?
一种方法:继承SaveButton,重载OnBubbleEvent方法。对私有的方法,我们全部采用反射来调用。
这种方法其实是可行的,但是好像有一点“丑陋”。
第二种方法:我们是不是可以简化它的代码?我们重写的按钮只是用在有限的地方,不需要考虑的那么全面。
当我闷头探索第二种方法的时候,想到了第三种方法--我不要管它原来的代码,只接调用ListItem的Add方法不行吗?只要取到当前的所有字段,遍历即可。
取列表的所有字段,可以调用基类的 this.ItemContext.FormContext.FieldControlCollection类获得。
下面是实现代码:
的Button),但并不处理,而是把事件“冒上去”,由父控件进行拦截处理(OnBubbleEvent方法)。
(既然是这样,我们用一个图片按钮来取代那个diidIOSaveItem应该也是可以的,只要ID和CommandName不变。)
言归正传---------------我第一次看到SaveButton控件的核心代码的时候,感到有点晕,太复杂了~ 而且,里面的很多内部方法都是私有的!
怎么改?
一种方法:继承SaveButton,重载OnBubbleEvent方法。对私有的方法,我们全部采用反射来调用。
这种方法其实是可行的,但是好像有一点“丑陋”。
第二种方法:我们是不是可以简化它的代码?我们重写的按钮只是用在有限的地方,不需要考虑的那么全面。
当我闷头探索第二种方法的时候,想到了第三种方法--我不要管它原来的代码,只接调用ListItem的Add方法不行吗?只要取到当前的所有字段,遍历即可。
取列表的所有字段,可以调用基类的 this.ItemContext.FormContext.FieldControlCollection类获得。
下面是实现代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;
using System.Security.Permissions;
using Microsoft.SharePoint.Utilities
namespace CodeArt.SharePoint
{
/// <summary>
/// 列表表单保存按钮,保存后返回本页面,
/// </summary>
public class FormSaveButton : SaveButton
{
//return true stop event bubble
//return false cotinue
protected override bool OnBubbleEvent(object source, EventArgs e)
{
this.Page.Validate();
if (!this.Page.IsValid)
{
return true ;
}
//some valid code
try
{
SaveData();
return true ;
}
catch (Exception ex)
{
throw new SPException(ex.Message,ex);
}
Page.Response.Redirect("/");
}
void SaveData()
{
SPListItem listItem;
if (this.ControlMode == SPControlMode.New)
listItem = this.List.Items.Add();
else
listItem = this.ListItem;
foreach (BaseFieldControl f in this.ItemContext.FormContext.FieldControlCollection)
{
try
{
//some valid code here --if(f.FieldName="XX") do something...
if (!f.Field.ReadOnlyField)
listItem[f.FieldName] = f.Value;
}
catch (ArgumentException) { }
}
listItem.Update();
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;
using System.Security.Permissions;
using Microsoft.SharePoint.Utilities
namespace CodeArt.SharePoint
{
/// <summary>
/// 列表表单保存按钮,保存后返回本页面,
/// </summary>
public class FormSaveButton : SaveButton
{
//return true stop event bubble
//return false cotinue
protected override bool OnBubbleEvent(object source, EventArgs e)
{
this.Page.Validate();
if (!this.Page.IsValid)
{
return true ;
}
//some valid code
try
{
SaveData();
return true ;
}
catch (Exception ex)
{
throw new SPException(ex.Message,ex);
}
Page.Response.Redirect("/");
}
void SaveData()
{
SPListItem listItem;
if (this.ControlMode == SPControlMode.New)
listItem = this.List.Items.Add();
else
listItem = this.ListItem;
foreach (BaseFieldControl f in this.ItemContext.FormContext.FieldControlCollection)
{
try
{
//some valid code here --if(f.FieldName="XX") do something...
if (!f.Field.ReadOnlyField)
listItem[f.FieldName] = f.Value;
}
catch (ArgumentException) { }
}
listItem.Update();
}
}
}
这个FormSaveButton 的保存前后的行为可以由我们任意控制了。把它编译成dll,然后嵌入RenderingTemplate即可。
附:
SaveButton,FormField这类控件可以称为“表单控件”,它们实现对列表表单的操作,或者是呈现一个字段,后者是显示一个保存按钮,或者是来迭代生成页面。
它们的继承关系如下:
SaveButton 》 FormComponent 》 TemplateBasedControl》SPControl》 Control
FormField 》 BaseFieldControl 》 FieldMetadata》FormComponent 》 TemplateBasedControl 》SPControl》 Control
所有的“表单控件”都继承于 TemplateBasedControl,都可以通过修改模板或重载替换已有控件来控制它的内容。
附:
SaveButton,FormField这类控件可以称为“表单控件”,它们实现对列表表单的操作,或者是呈现一个字段,后者是显示一个保存按钮,或者是来迭代生成页面。
它们的继承关系如下:
SaveButton 》 FormComponent 》 TemplateBasedControl》SPControl》 Control
FormField 》 BaseFieldControl 》 FieldMetadata》FormComponent 》 TemplateBasedControl 》SPControl》 Control
所有的“表单控件”都继承于 TemplateBasedControl,都可以通过修改模板或重载替换已有控件来控制它的内容。
转载于:https://blog.51cto.com/jeffluo/102573