首页 > 代码库 > SharePoint开发 - 自定义导航菜单(一)菜单声明与配置

SharePoint开发 - 自定义导航菜单(一)菜单声明与配置

本篇描述自定义sharepoint菜单的一种方式,自定义菜单适用于一些门户等需求的网站

自定义的菜单有自己的数据源,可以是数据表,可以是XML,本篇叙述的是采用XML数据源作为菜单的声明定义部分,将XML以文件的格式保存到网站中自己创建的配置文档库中

XML菜单的格式形如下面的格式,其中有菜单标题title属性,有菜单所属的权限用户组SPGroups属性,有菜单的链接url属性,实际应用中可以添加更多的字段。

<SiteMap>
  <SiteMapNode title="我的项目" SPGroups="质量技术中心;造价中心;分公司;第3分公司;工程部;资金中心;核算中心;运营中心;内审中心;财务中心;核算中心;测试组;资金组" >
<SiteMapNode title="项目管理" url="/_layouts/SP_MIP/PI/PI_BasicInfoSearchInfo.aspx" SPGroups="质量技术中心;资金中心;核算中心;造价中心;财务中心;分公司;第3分公司;工程部;运营中心;内审中心;核算中心;测试组;资金组"/>
  </SiteMapNode>
</SiteMap>
我们要给网站管理员提供一个接口来定义导航菜单,比如放到网站设置里,如图所示


新建一个SharePoint解决方案,添加一个元素Element用来定义这个网站设置菜单(CustomActionGroup和CustomAction节点)。代码如下(这里包含我后期添加的一个用户修改密码的功能,这里不做说明)

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomActionGroup
     Id="SPMIPNavigation"
     Title="SPMIP导航"
     Description = "SPMIP导航"
     Location = "Microsoft.SharePoint.SiteSettings"
     Sequence = "1999"
     ImageUrl="/_layouts/Images/SiteSettings_SPMIPNavigation_48x48.png">
  </CustomActionGroup>
  <CustomAction
    Id="SPMIPTopNav"
    GroupId="SPMIPNavigation"
    Location="Microsoft.SharePoint.SiteSettings"
    Rights="ManageWeb"
    Sequence="2000"
    Title="顶部导航"
    Description="顶部导航">
    <UrlAction Url="{SiteUrl}/_layouts/SP_MIP/TopNav.aspx" />
  </CustomAction>
  <CustomAction
    Id="SPMIPLeftNav"
    GroupId="SPMIPNavigation"
    Location="Microsoft.SharePoint.SiteSettings"
    Rights="ManageWeb"
    Sequence="2010"
    Title="左侧导航"
    Description="左侧导航">
    <UrlAction Url="{SiteUrl}/_layouts/SP_MIP/LeftNav.aspx" />
  </CustomAction>
  <CustomAction
    Id="SPMIPChangePassword"
    GroupId="PersonalActions"
    Location="Microsoft.SharePoint.StandardMenu"
    Sequence="1000"
    Title="修改密码"
    Description="修改密码"
    ImageUrl="{SiteUrl}/_layouts/images/Welcome_SPMIPChangePwd_32x32.png">
    <UrlAction Url="javascript:Show();"/>
  </CustomAction>
</Elements>
添加相应的网站资产,如设置图片。添加两个页面TopNav.aspx和LeftNav.aspx。两个页面其实没什么区别,以TopNav为例,添加一个多行文本框,一个保存按钮就可以了。


核心页面代码

<table border="0" width="100%" cellspacing="0" cellpadding="0">
        <wssuc:InputFormSection ID="InputFormSection" Title="顶部导航" runat="server" Description="顶部导航">
            <Template_InputFormControls>
                <wssuc:InputFormControl ID="InputFormControl" runat="server">
                    <Template_Control>
                        <table border="0" cellpadding="0" cellspacing="0">
                            <tr>
                                <td align="right" style="padding-bottom: 5px">
                                    <a href="javascript:topnav_showFullScreen('<%= txtNavXml.ClientID %>', '<%= txtNavXmlPop.ClientID %>');"
                                        style="color: #0072bc;">
                                        <asp:Literal ID="ltl" runat="server" Text="全屏编辑" />
                                    </a>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <asp:TextBox ID="txtNavXml" runat="server" Wrap="false" TextMode="MultiLine" Rows="22"
                                        Width="600px" />
                                </td>
                            </tr>
                        </table>
                    </Template_Control>
                </wssuc:InputFormControl>
            </Template_InputFormControls>
        </wssuc:InputFormSection>
        <wssuc:ButtonSection ID="bts" runat="server" ShowStandardCancelButton="false">
            <Template_Buttons>
                <asp:Button runat="server" class="ms-ButtonHeightWidth" Text="保存" ID="btnSave" OnClick="btnSave_OnClick" />
                <asp:Button runat="server" class="ms-ButtonHeightWidth" Text="取消" ID="btnClose" OnClientClick="TopNav_Close_Click(); return false;" />
            </Template_Buttons>
        </wssuc:ButtonSection>
    </table>
    <table id="tblFullScreen" border="0" cellpadding="0" cellspacing="0" class="tblPop">
        <tr>
            <td align="center" valign="top">
                <table border="0" cellpadding="5" cellspacing="0" width="100%">
                    <tr>
                        <td>
                            <asp:TextBox ID="txtNavXmlPop" runat="server" Wrap="false" TextMode="MultiLine" Rows="28"
                                Width="99%" />
                        </td>
                    </tr>
                    <tr>
                        <td align="center">
                            <a href="javascript:topnav_hideFullScreen('<%= txtNavXml.ClientID %>', '<%= txtNavXmlPop.ClientID %>');"
                                style="color: #0072bc;">
                                <asp:Literal ID="ltlClose" runat="server" Text="关闭" />
                            </a>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
按钮后台的处理事件要做的事情就是把XML配置文件的内容读取出来,并把用户更改的XML定义保存回文档库的XML文件中。

protected void btnSave_OnClick(object sender, EventArgs e)
        {
            try
            {
                Config.Save(base.Web, this.txtNavXml.Text, Config.NavType.Top);
                SPUtility.Redirect("settings.aspx", SPRedirectFlags.RelativeToLayoutsPage, HttpContext.Current);
            }
            catch (Exception exception)
            {
                SPMIPTrace.WriteError("SPMIPNavigation", exception);
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!base.IsPostBack)
            {
                this.txtNavXml.Text = Config.Load(base.Web, Config.NavType.Top);
            }
        }
 class Config
    {
        public static string Load(SPWeb web, NavType navType)
        {
            string str = null;
            try
            {
                StreamReader reader;
                SPList settingList = SPMIPUtility.CheckSettingList("SPMIPSetting");
                switch (navType)
                {
                    case NavType.Top:
                        {
                            SPFile topNavSettingFile = settingList.RootFolder.Files["TopNav.xml"];
                            if (topNavSettingFile.Exists)
                            {
                                using (reader = new StreamReader(topNavSettingFile.OpenBinaryStream()))
                                {
                                    str = reader.ReadToEnd();
                                }
                            }
                            break;
                        }
                    case NavType.Left:
                        {
                            SPFile leftNavSettingFile = settingList.RootFolder.Files["LeftNav.xml"];
                            if (leftNavSettingFile.Exists)
                            {
                                using (reader = new StreamReader(leftNavSettingFile.OpenBinaryStream()))
                                {
                                    str = reader.ReadToEnd();
                                }
                            }
                            break;
                        }
                }
                return str;
            }
            catch (Exception exception)
            {
                SPMIPTrace.WriteError("SPMIPNavigation", exception);
                return str;
            }
        }

        public static bool Save(SPWeb web, string fileContent, NavType navType)
        {
            bool flag = false;
            try
            {
                SPList settingList = SPMIPUtility.CheckSettingList("SPMIPSetting");
                byte[] bytes = Encoding.UTF8.GetBytes(fileContent);
                web.AllowUnsafeUpdates = true;
                switch (navType)
                {
                    case NavType.Top:
                        settingList.RootFolder.Files.Add("TopNav.xml", bytes, true);
                        break;
                    case NavType.Left:
                        settingList.RootFolder.Files.Add("LeftNav.xml", bytes, true);
                        break;
                }
                flag = true;
            }
            catch (Exception exception)
            {
                SPMIPTrace.WriteError("SPMIPNavigation", exception);
            }
            return flag;
        }

        public enum NavType
        {
            Top,
            Left
        }
    }
大致的功能就完成了,下一讲叙述如何在母版页应用这个菜单声明。





SharePoint开发 - 自定义导航菜单(一)菜单声明与配置