【原创】SharePoint2010的SaveButton如何实现在跳转前给用户以提示[How to implement SaveButton display an alert when Redirect action]

SharePoint 2010 的SaveButton控件在保存数据后,会跳转到Url参数中的Source指定的页面,如要没有Source则跳转到List的默认页面。有的时候,需要在保存后能够给用户一个提示再进行跳转,这就要修改SaveButton的默认行为,当然最简单的方式就是继承SaveButton,然后进行客户端方式的跳转。幸运的是,SaveButton并非是定义为sealed的,所以继承是没有问题的,所以我定义了SaveButtonEx类。

public class SaveButtonEx : Microsoft.SharePoint.WebControls.SaveButton

定义两个属性,定义是否为客户端跳转

    /// <summary>
        /// 是否是客户端跳转
        /// </summary>
        public Boolean IsClientRedirect
        {
            get;
            set;
        }

        /// <summary>
        /// 跳转前的消息
        /// </summary>
        public string RedirectMessage
        {
            get;
            set;
        }

 

关键的地方在于能够重写其被Click时候的行为,本质上SaveButton并不是直接继承的Button控件,而是通过在CreateChildControls中包装了Button控件实现的,所以要重写的方法是OnBubbleEvent,而不是OnClick.

[SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
protected override bool OnBubbleEvent(object source, EventArgs e)
{
    bool flag = false;
    if (e is CommandEventArgs)
    {
        CommandEventArgs args = (CommandEventArgs)e;
        if (!(args.CommandName == "SaveItem"))
        {
            return flag;
        }
        SPListItem listItem = base.ItemContext.ListItem;
        SPContentType contentType = ReflectorUtils.getPerperty<SPContentType>("ContentType", base.ItemContext);
        if (((listItem != null) && (contentType != null)) && !ReflectorUtils.getPerperty<bool>("HasExternalDataSource", listItem))
        {
            try
            {
                listItem["ContentType"] = contentType.Name;
                ReflectorUtils.InvokeMethod(listItem, "SetExtraInfo", new object[] { "ContentTypeId", contentType.Id.ToString(), "" });
            }
            catch (ArgumentException)
            {
            }
        }
        this.Page.Validate();
        if (!this.Page.IsValid)
        {
            return true;
        }
        bool flag2 = false;
        EventHandler onSaveHandler = base.ItemContext.FormContext.OnSaveHandler;
        if (onSaveHandler != null)
        {
            ReflectorUtils.InvokeMethod(typeof(Microsoft.SharePoint.WebControls.SaveButton), null, "ActionBeforeSaveItem", new object[] { ItemContext });

            onSaveHandler(this, EventArgs.Empty);
            flag2 = ((ReflectorUtils.getPerperty<object>("FieldValidationFailures", base.ItemContext.FormContext) == null)
                && (ReflectorUtils.getPerperty<object>("ItemValidationFailure", base.ItemContext.FormContext) == null))
                && (ReflectorUtils.getPerperty<object>("UniqueFieldsWithDuplicateValues", base.ItemContext.FormContext) == null);
        }
        else if (base.List.BaseTemplate == SPListTemplateType.Survey)
        {
            if (ReflectorUtils.getPerperty<object>("NextFieldName", base.ItemContext.FormContext) == null)
            {
                ReflectorUtils.InvokeMethod(listItem, "Checkin", null);
                flag2 = true;
            }
            else if (base.ControlMode == SPControlMode.New)
            {
                ReflectorUtils.InvokeMethod(listItem, "Checkout", null);
                flag2 = true;
            }
            else
            {
                flag2 = this.SaveItem();
            }
        }
        else
        {
            flag2 = this.SaveItem();
        }
        flag = true;
        if (!flag2)
        {
            return flag;
        }
        string redirectUrl = base.RedirectUrl;
        ReflectorUtils.setPerperty("InSavePostBack", base.ItemContext, true, null);         //这里特别要测试一下会不会有异常

        bool needToCreateWorkSpace = (bool)ReflectorUtils.InvokeMethod(typeof(Microsoft.SharePoint.WebControls.SaveButton), this, "NeedToCreateWorkSpace", new object[] { });
        if (needToCreateWorkSpace)
        {
            ReflectorUtils.InvokeMethod(typeof(Microsoft.SharePoint.WebControls.SaveButton), this, "GotoMeetingWorkspaceCreationPage", new object[] { redirectUrl });
            return flag;
        }
        if (!base.ItemContext.IsPopUI)
        {
            if (base.ItemContext.List.BaseType == SPBaseType.DocumentLibrary)
            {
                SPFile file = ((SPListItem)base.Item).File;
                if (file != null)
                {
                    redirectUrl = file.ServerRelativeUrl;
                }
                else
                {
                    SPFolder folder = ((SPListItem)base.Item).Folder;
                    if (folder != null)
                    {
                        redirectUrl = folder.ServerRelativeUrl;
                    }
                    else
                    {
                        redirectUrl = ReflectorUtils.getPerperty<string>("RootFolderUrl", base.ItemContext.List);
                    }
                }
            }
            if (!this.IsClientRedirect)
            {
                SPUtility.Redirect(redirectUrl, SPRedirectFlags.UseSource, this.Context);
            }
            else
            {
                this.Context.Response.Write(
                    "<script type='text/javascript'>alert('" + this.RedirectMessage +
                        "');window.location.href='" + redirectUrl + "';</script>");
                this.Context.Response.Flush();
                this.Context.Response.End();
            }
            return flag;
        }
        if ((listItem != null) && (listItem.File != null))
        {
            string serverRelativeUrl = listItem.File.ServerRelativeUrl;
            this.Context.Response.Write(string.Format(CultureInfo.InvariantCulture, "<script type='text/javascript'>\r\n                                    retVal = {{}};\r\n                                    retVal['newFileUrl'] = \"{0}\";\r\n                                    window.frameElement.commitPopup(retVal);\r\n                                    </script>", new object[] { serverRelativeUrl }));
        }
        else
        {
            this.Context.Response.Write("<script type='text/javascript'>window.frameElement.commitPopup();</script>");
        }
        this.Context.Response.Flush();
        this.Context.Response.End();
    }
    return flag;
}

当然,这里面的大部分代码我只是从反编译的代码中复制过来的.其中涉及到一些internal的private的方法及属性,需要使用反射的方式进行调用。

对于跳转的方法其实就很简单了,就是判断是否为客户端跳转,是的话就注册一段脚本,输出alert以及通过window对象进行跳转。下面是这段代码

if (!this.IsClientRedirect)
{
SPUtility.Redirect(redirectUrl, SPRedirectFlags.UseSource, this.Context);
}
else
{
this.Context.Response.Write(
    "<script type='text/javascript'>alert('" + this.RedirectMessage +
        "');window.location.href='" + redirectUrl + "';</script>");
this.Context.Response.Flush();
this.Context.Response.End();
}

下面是反射辅助类的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Only.SPLibraryExtend.Utils
{
    /// <summary>
    /// 反射工具
    /// </summary>
    public class ReflectorUtils
    {
        public static void setField(Type type,string fieldName, object o, object value)
        {            
            FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
            fi.SetValue(o, value);
        }

        public static void setField(string fieldName,object o,object value)
        {
            setField(o.GetType(), fieldName, o, value);
        }

        public static T getField<T>(Type type,string fieldName, object o)
        {
            T result = default(T);
            
            FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
            result = (T)fi.GetValue(o);

            return result;
        }

        public static T getField<T>(string fieldName, object o)
        {
            return getField<T>(o.GetType(), fieldName, o);
        }
        /// <summary>
        /// 获取反射的属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        public static T getPerperty<T>(string property, object o)
        {
            T result;

            Type t = o.GetType();

            PropertyInfo pi = t.GetProperty(property, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic);
            result = (T)pi.GetValue(o, null);

            return result;
        }

        public static void setPerperty(string property, object o,object value,object[] index)
        {
          
            Type t = o.GetType();

            PropertyInfo pi = t.GetProperty(property,  BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetProperty);            
            pi.SetValue(o, value, index);

        }

        public static object InvokeMethod(object target, string methodName, object[] parameters)
        {
            return InvokeMethod(target.GetType(), target, methodName, parameters);
        }

        /// <summary>
        /// 反射调用非重载方法
        /// </summary>
        /// <param name="t"></param>
        /// <param name="target"></param>
        /// <param name="methodName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static object InvokeMethod(Type t, object target, string methodName, object[] parameters)
        {
            MethodInfo method = null;
            if (target == null)
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
            }
            else
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            }
            var result = method.Invoke(target, parameters);
            return result;
        }

        /// <summary>
        /// 反射调用重载的方法
        /// </summary>
        /// <param name="t"></param>
        /// <param name="target"></param>
        /// <param name="methodName"></param>
        /// <param name="parameters"></param>
        /// <param name="parameterTypes"></param>
        /// <returns></returns>
        public static object InvokeMethod(Type t, object target, string methodName, object[] parameters, Type[] parameterTypes)
        {
            MethodInfo method = null;
            if (target == null)
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, Type.DefaultBinder, parameterTypes, null);
            }
            else
            {
                method = t.GetMethod(methodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder, parameterTypes, null);
            }
            var result = method.Invoke(target, parameters);
            return result;
        }
    }
}

 

这个控件的运行效果,请参见:http://www.cnblogs.com/fxwdl/archive/2012/08/30/2663182.html

 

Technorati 标签: SharePoint,SaveButton

 
posted @ 2012-08-30 09:22  吴东雷  阅读(913)  评论(1编辑  收藏  举报