设为首页 收藏本站
查看: 934|回复: 0

[经验分享] 在SharePoint中使用自定义的服务器控件(Web Control)

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-9-24 09:48:48 | 显示全部楼层 |阅读模式
  SharePoint的开发中,我们经常需要自己开发一些服务器控件,然后把它添加到MOSS的页面上。
  SharePoint服务器控件的开发跟普通的asp.net服务器控件没有区别,只不过是在部署的时候需要进行一些特别的配置。
  下面拿一个具体的例子来说明这个过程。
  以下的示例是一个自定义的导航服务器控件(WebFolderNavigation),这个导航控件的第一级为所有显示在导航栏上的列表或文档库链接,列表或文档库链接的子级为相应的文件夹。效果图如下:
DSC0000.png
  
Step1: 新建一个Asp.net Server Control项目,名称为CodeArt.SharePoint.WebControls。(或普通的类库项目,添加System.Web的引用。)
  
  Step2:因为WebFolderNavigation控件需要访问SharePoint的对象模型,所有添加对Microsoft.SharePoint.dll的引用。
  
  Step3: WebFolderNavigation控件的代码如下:
  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.Navigation;
  using System.Web.UI;
  namespace CodeArt.SharePoint.WebControls
  {
  /// <summary>
  /// 当前站点文件夹导航
  /// </summary>
  public class WebFolderNavigation : Menu
  {
  const String SORT_FIELD_NAME = "排序号";
  const String SHOW_SUB_FIELD_NAME = "显示子栏目";
  private bool _EnableSort = false;
  public bool EnableSort
  {
  get { return _EnableSort; }
  set { _EnableSort = value; }
  }
  
  private int _MaxFolderDepth = 2;
  public int MaxFolderDepth
  {
  get { return _MaxFolderDepth; }
  set { _MaxFolderDepth = value; }
  }
  protected override void CreateChildControls()
  {
  if ( this.Items.Count > 0)
  return;
  base.CreateChildControls();
  SPWeb web = SPContext.Current.Web;
  string webUrl = web.ServerRelativeUrl;
  if (!webUrl.EndsWith("/"))
  webUrl += "/";
  Dictionary<string, SPList> allVisibleList = new Dictionary<string, SPList>();
  foreach (SPList list in web.Lists)
  {
  if (list.OnQuickLaunch)
  allVisibleList.Add(list.DefaultViewUrl.ToLower() , list);
  }
  List<SPNavigationNode> navLinks = new List<SPNavigationNode>();
  foreach (SPNavigationNode levelOneNode in web.Navigation.QuickLaunch)
  {
  if (levelOneNode.IsVisible)
  {
  foreach (SPNavigationNode levelTwoNode in levelOneNode.Children)
  {
  if (levelTwoNode.IsVisible)
  {
  navLinks.Add(levelTwoNode);
  }
  }
  }
  }
  foreach (SPNavigationNode node in navLinks)
  {
  if (allVisibleList.ContainsKey(node.Url.ToLower()))
  {
  SPList list = allVisibleList[node.Url.ToLower()];
  
  MenuItem rootItem = new MenuItem();
  rootItem.Text = list.Title;
  rootItem.ToolTip = list.Description ;
  
  rootItem.NavigateUrl = list.DefaultViewUrl;
  this.Items.Add(rootItem);
  
  string showSubFieldName = getShowSubFieldName(list);
  
  if (EnableSort)
  {
  string sortFieldName = getSortFieldName(list);
  
  if (sortFieldName == "")
  CreateItem(list.RootFolder, rootItem.ChildItems, webUrl, 1, showSubFieldName);
  else
  CreateItem(list.RootFolder, rootItem.ChildItems, webUrl, sortFieldName, 1, showSubFieldName);
  }
  else
  {
  CreateItem(list.RootFolder, rootItem.ChildItems, webUrl, 1, showSubFieldName);
  }
  }
  else
  {
  CreateItemByNavigationNode(this.Items, node);
  }
  }
  }
  void CreateItemByNavigationNode(MenuItemCollection items, SPNavigationNode node)
  {
  MenuItem item = new MenuItem();
  item.Text = node.Title ;
  item.NavigateUrl = node.Url ;
  items.Add(item);
  if (node.Children.Count == 0) return;
  foreach (SPNavigationNode n in node.Children )
  {
  CreateItemByNavigationNode(item.ChildItems, n);
  }
  }
  string getSortFieldName(SPList list)
  {
  if (list.Fields.ContainsField(SORT_FIELD_NAME))
  {
  SPField f = list.Fields.GetField(SORT_FIELD_NAME);
  return f.InternalName;
  }
  return "";
  }
  string getShowSubFieldName(SPList list)
  {
  if (list.Fields.ContainsField( SHOW_SUB_FIELD_NAME ))
  {
  SPField f = list.Fields.GetField(SHOW_SUB_FIELD_NAME);
  return f.InternalName;
  }
  return "";
  }
  bool ShowSubFolder(SPFolder folder, string showSubFieldName)
  {
  SPListItem folderItem = folder.Item;
  if (folderItem == null) return true;
  
  if ( folderItem.Fields.ContainsField(showSubFieldName))
  {
  object value = folder.Item[showSubFieldName];
  if( value == null )
  return false ;
  else
  return value.ToString().ToLower() == "true";
  }
  else
  {
  return true;
  }
  }
  void CreateItem(SPFolder folder, MenuItemCollection items, string webUrl, int depth, string showSubFieldName)
  {
  if (!ShowSubFolder(folder, showSubFieldName)) return;
  
  if (folder.SubFolders.Count == 0) return;
  foreach (SPFolder f in folder.SubFolders)
  {
  if (f.Item==null) continue; //说明是隐藏文件夹
  MenuItem item = new MenuItem();
  item.Text = f.Name;
  item.NavigateUrl = f.ServerRelativeUrl;
  items.Add(item);
  if (depth < this.MaxFolderDepth )
  {
  CreateItem(f, item.ChildItems, webUrl, depth + 1, showSubFieldName);
  }
  }
  }
  void CreateItem(SPFolder folder, MenuItemCollection items, string webUrl, string sortField, int depth, string showSubFieldName)
  {
  if (!ShowSubFolder(folder, showSubFieldName)) return;
  if (folder.SubFolders.Count == 0) return;
  IList<SPFolder> folders = SPUtil.GetSortedFolders(folder.SubFolders , sortField );
  foreach (SPFolder f in folders)
  {
  if (f.Item==null) continue;
  MenuItem item = new MenuItem();
  item.Text = f.Name;
  item.NavigateUrl = f.ServerRelativeUrl;
  items.Add(item);
  if (depth < MaxFolderDepth)
  CreateItem(f, item.ChildItems, webUrl, sortField, depth + 1, showSubFieldName);
  }
  }
  }
  }
  
  代码中用到的SPUtil类如下:
  

DSC0001.gif DSC0002.gif SPUtil
/// <summary>
    ///
    /// </summary>
    public class SPUtil
    {
        static public bool IsHiddenFolder(SPFolder f)
        {
            return f.Item == null;
            //return f.Properties.Count < 20;
        }

        static public string GetWebUrl( SPWeb web )
        {
            string webUrl = web.Url;
            if (!webUrl.EndsWith("/"))
                webUrl += "/";

            return webUrl;
        }

        public static StringDictionary GetFieldDictionary(SPList list)
        {
            StringDictionary fields = new StringDictionary();

            foreach (SPField f in list.Fields)
            {
                if (fields.ContainsKey(f.Title)) continue;

                fields.Add(f.Title, f.InternalName);
            }

            return fields;
        }


        static public int[] GetSelectedItemIDs( SPList list )
        {
            return GetSelectedItemIDs( list.ID.ToString() ) ;
        }

        static public int[] GetSelectedItemIDs(string listId )
        {
            if (System.Web.HttpContext.Current == null)
                throw new SPException("context is null.");

            string ids = System.Web.HttpContext.Current.Request["spItemSelectionCheckBox_" + listId];

            if (ids == null || ids == "")
                return null;

            String[] arr = ids.Split(',');

            int[] intIDs = new int[arr.Length];

            for (int i = 0; i < arr.Length; i++)
            {
                intIDs = Convert.ToInt32(arr);
            }

            return intIDs;
        }

        /// <summary>
        /// 修改视图中的查询条件部分
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="query"></param>
        static public void ChangeSchemaXmlQuery(XmlDocument doc, string query)
        {
            if (String.IsNullOrEmpty(query)) return;

            string innerQuery = GetInnerQuery(query);
            if (innerQuery == "") return;

            XmlNode queryNode = doc.DocumentElement.SelectSingleNode("Query");
            //queryNode.InnerXml = qxml;

            XmlNode whereNode = queryNode.SelectSingleNode("Where");

            if (whereNode != null)
                queryNode.RemoveChild(whereNode);

            XmlNode newWhereNode = doc.CreateElement("Where");
            newWhereNode.InnerXml = innerQuery;

            queryNode.AppendChild(newWhereNode);

            XmlNode ViewEmptyNode = doc.DocumentElement.SelectSingleNode("ViewEmpty");

            ViewEmptyNode.InnerXml = "<HTML><![CDATA[<font color='red'><b>未找到符合查询条件的记录。</b></font>]]></HTML>";

        }

        /// <summary>
        /// 设置视图xml中的查询条件
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="query1">条件1</param>
        /// <param name="query2">条件2</param>
        static public void ChangeSchemaXmlQuery(XmlDocument doc, string query1 , string query2)
        {
            string query = "";

            string innerQuery = GetInnerQuery(query1);           

            string innerQuery2 = GetInnerQuery(query2);

            if (innerQuery == "" && innerQuery2 == "" ) return;

            if (innerQuery != "" && innerQuery2 != "")
                query = "<And>" + innerQuery + innerQuery2 + "</And>" ;
            else
                query = innerQuery + innerQuery2 ;

            XmlNode queryNode = doc.DocumentElement.SelectSingleNode("Query");
            //queryNode.InnerXml = qxml;

            XmlNode whereNode = queryNode.SelectSingleNode("Where");

            if (whereNode != null)
                queryNode.RemoveChild(whereNode);

            XmlNode newWhereNode = doc.CreateElement("Where");
            newWhereNode.InnerXml = query;

            queryNode.AppendChild(newWhereNode);

            XmlNode ViewEmptyNode = doc.DocumentElement.SelectSingleNode("ViewEmpty");

            ViewEmptyNode.InnerXml = "<HTML><![CDATA[<font color='red'><b>未找到符合查询条件的记录。</b></font>]]></HTML>";

        }


        static string GetInnerQuery(string q)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml("<Query>" + q + "</Query>");

            XmlNode whereNode = doc.DocumentElement.SelectSingleNode("Where");

            if (whereNode != null)
                return whereNode.InnerXml;
            else
                return "";
        }



        /// <summary>
        /// 获取ViewXml中的排序结
        /// </summary>
        /// <param name="viewXml"></param>
        /// <returns></returns>
       public static string GetOrderBySection( string viewXml )
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(viewXml);

            XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("OrderBy");

            if (nodes == null || nodes.Count == 0)
                return "";
            else
                return nodes[0].OuterXml;
        }

        /// <summary>
        /// 指定ID的试图是否存在
        /// </summary>
        /// <param name="views"></param>
        /// <param name="viewId"></param>
        /// <returns></returns>
        static public bool ViewExist(SPViewCollection views, Guid viewId)
        {
            foreach (SPView view in views)
            {
                if (view.ID == viewId)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 获取按名称排序后的子文件夹列表
        /// </summary>
        /// <param name="folders"></param>
        /// <returns></returns>
        static public IList<SPFolder> GetSortedFolders(SPFolderCollection folders)
        {
            List<SPFolder> sortedFolders = new List<SPFolder>();

            foreach (SPFolder f in folders)
            {
                if (f.Item != null) //为非系统文件夹
                    sortedFolders.Add(f);
            }

            sortedFolders.Sort(CompareFolder);

            return sortedFolders;
        }

        static int CompareFolder(SPFolder f1, SPFolder f2)
        {
            return f1.Name.CompareTo(f2.Name);
        }

        /// <summary>
        /// 获取按某个字段排序后的子文件夹
        /// </summary>
        /// <param name="folders"></param>
        /// <param name="sortFieldName"></param>
        /// <returns></returns>
        static public IList<SPFolder> GetSortedFolders(SPFolderCollection folders , string sortFieldName )
        {
           
            List<SPFolder> sortedFolders = new List<SPFolder>();

            foreach (SPFolder f in folders)
            {
                if( f.Item != null ) //为非系统文件夹
                    sortedFolders.Add(f);
            }

            SPFolderComparer c = new SPFolderComparer(sortFieldName);

            sortedFolders.Sort(c);

            return sortedFolders;
        }

        class SPFolderComparer : IComparer<SPFolder>
        {
            private string _sortFieldName;
            public SPFolderComparer(string sortFieldName)
            {
                _sortFieldName = sortFieldName;
            }

            #region IComparer<SPFolder> 成员

            public int Compare(SPFolder x, SPFolder y)
            {
                //if (IsHiddenFolder(x) || IsHiddenFolder(y)) return 0;               

                if (!x.Item.Fields.ContainsField(_sortFieldName) || !y.Item.Fields.ContainsField(_sortFieldName))
                    return 0;

                string sX = "" + x.Item[_sortFieldName];
                if (sX == "")
                    sX = "0";

                string sY = "" + y.Item[_sortFieldName];
                if (sY == "")
                    sY = "0";

                return Convert.ToInt32( sX ).CompareTo( Convert.ToInt32(sY) ) ;
               
            }

            #endregion
        }

    }  
  WebFolderNavigation 直接继承于Menu,用递规遍历站点的所有列表和子文件夹来创建Menu的子菜单项。考虑到了对列表和文件夹的排序支持,
  列表的排序通过站点的导航数据进行,文件夹的排序通过给文件夹添加一个"排序号"的栏来实现(给文件夹添加栏参考:WSS 扩展文件夹的属性--如何给文件夹添加扩展字段 )。
  
  Step4: SharePoint上的服务器控件可以部署到站点下的bin目录,也可以部署到GAC中,经验之谈,建议部署到GAC中,那么首先需要给项目进行签名。
DSC0003.png
  
  Step5: 把dll部署到GAC。
  可以直接把debug目录下的dll拖入C:\WINDOWS\assembly目录,也可以写个命令行脚本来自动化操作.开发的过程中要不断的把dll放入GAC,然后重启IIS应用程序池,
  所以,最好还是采用脚本来操作:在项目根目录下创建一个文本文件,改名为deployGAC.cmd , 添加以下内容:
  echo Adding assemblies to the GAC...
  "%programfiles%\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" -if bin\Debug\CodeArt.SharePoint.WebControls.dll
  iisapp /a "SharePoint - 81" /r
  iisapp是重启应用程序池的命令,"SharePoint &#8211; 81为应用程序池的名称,请修改为自己开发环境的应用程序池名称。
  
  Step6: 利用reflector找到的dll的全名:CodeArt.SharePoint.WebControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a525f21aa237e5b
  
  Step7: 配置SafeControl。
  SharePoint站点页面中使用的所有服务器控件必须在应用程序的web.config中进行配置(这样做是为了安全原因,防止普通用户通过站点上传一个dll来运行)。
  打开应用程序的web.config文件(一般为C:\Inetpub\wwwroot\wss\VirtualDirectories\XXX\web.cofig),在<SafeControls>节点下添加如下配置:
  <SafeControl Assembly=" CodeArt.SharePoint.WebControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a525f21aa237e5b" Namespace=" CodeArt.SharePoint.WebControls " TypeName="*" Safe="True" />
  
  Step8: WebFolderNavigation应该添加进站点的母板页里。用SPD打开站点,打开要修改的母板页。首先添加dll的Register指令。在<html标签上方添加:
  <%@ Register Assembly=" CodeArt.SharePoint.WebControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a525f21aa237e5b" Namespace=" CodeArt.SharePoint.WebControls " TagPrefix="codeart" %>
  
  Step9: 我们修改的是导航控件,所有,需要把WebFolderNavigation放入<Sharepoint:SPNavigationManager这个服务器控件内部:
  <Sharepoint:SPNavigationManager
                  id="QuickLaunchNavigationManager"
                  runat="server"
                  QuickLaunchControlId="SiteNavigation1"
                  ContainedControl="QuickLaunch"
                  EnableViewState="false">
      < codeart: WebFolderNavigation ID="WebFolderNavigation1" runat="server" />
  </Sharepoint:SPNavigationManager>
  
  Step10:   保存并发布母板页。

  
  Game over.
  注意:CodeArt.SharePoint.WebControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9a525f21aa237e5b中的PublicKeyToken值请用自己dll的值。
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-118059-1-1.html 上篇帖子: Sharepoint学习笔记—Ribbon系列-- 8.在Site上创建(或隐藏)Ribbon Tabs 下篇帖子: SharePoint 2010中的客户端AJAX应用——对话框显示详细信息页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表