Saturday, April 18, 2009

Adding Breadcrumb Navigation for SharePoint Application Pages Programmatically



When creating a new Application Page (an .aspx page deployed to the c:\program files\common files\microsoft shared\web server extensions\12\template\layouts directory) you can easily manually fill the content place holder provided by the application.master in order to obtain a page that seems really to be an Out of The Box SharePoint Application Page.

Page Title (Browser Page Title)

<asp:Content ID="Content4" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
    <SharePoint:EncodedLiteral ID="EncodedLiteral2" runat="server" Text="Delete Items" EncodeMethod='HtmlEncode' />
</asp:Content>

Page Title (Displayed in th Application Page)

<asp:Content ID="Content3" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    <SharePoint:EncodedLiteral ID="EncodedLiteral1" runat="server" Text="Delete Items from a Custom List" EncodeMethod='HtmlEncode' />
</asp:Content>

Page Description (Displayed in th Application Page)

<asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderPageDescription" runat="server">
    <SharePoint:EncodedLiteral ID="EncodedLiteral3" runat="server" Text="Use this page to delete items from a Custom List" EncodeMethod='HtmlEncode' />
</asp:Content>

The above code sample will produce the following result:

There is one thing that you cannot perform manually using Content Place Holder, it is the Breadcrumb Navigation.

You have two ways of adding Breadcrumb Navigation for SharePoint Application Pages:

  1. Adding a siteMapNode element in the layouts.sitemap
    Jan Tielens has written several posts on that topic. The exposed several approaches use xml files and deployment techniques in order to make your custom Application Page to be known by SharePoint as one of its native Application Pages. Doing that allows the native SharePoint breadcrumb generating mechanism to place automatically a Breadcrumb in your custom Application Page.
  2. For more information you can visit:
    Adding Breadcrumb Navigation for SharePoint Application Pages
    Adding Breadcrumb Navigation to SharePoint Application Pages, the Easy Way
    Adding Breadcrumb Navigation to Application Pages in SharePoint Central Administration

  3. Adding Breadcrumb Programmatically
  4. This approach uses server-side code (C# or VB .Net). It is the opposite approach compared to Jan's one because we will customize SharePoint only at the page level.

    Pros:
    Your SharePoint customizations of the Application Page stay at the level of the page, so you can deploy all using a single Feature.
    You can build your own navigation (SiteCollection Root Web > Web Site1 >..> Web Site n,  Web Site n > List, Web Site n > Doc Lib, etc.) 

    Cons:
    You have to decide about what navigation you want.
    You have to build the navigation using C# or VB .Net.
    You might have to put parameters in the URL when calling the page (List ID, Doc Lib ID, Page Name,etc.) if you do not use a CustomAction Element to call the Application Page.

In the following code sample I will programmatically, using C#, add a breadcrumb to an Application Page called by a new entry in the Action Menu of a list.

So, with this UrlAction :

<UrlAction Url="~site/_layouts/custom directory/myCustomApplicationPage.aspx?id={ListId}"/>

 

The steps are the followings:

  • At the first Load of the page 
    Getting the Breadcrumb element(s) from URL and/or SPContext 
    Storing some of the elements in an Hidden Control for the PostBack of the page.
  • For the Postback
    Getting the Breadcrumb element(s) from the Hidden Control.
  • In any case
    Building the Breadcrumb HTML
    Override the RenderChildren method of the Application page to fill the PlaceHolderTitleBreadcrumb with the Breadcrumb HTML 

  • The following code sample shows how to perform these operations using C#:

        <asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderMain" runat="server">

            <br />

            <br />

            <asp:Label ID="lblItemsToDeleteList" runat="server"></asp:Label>

            <br />

            <br />

            <input type="hidden" runat="server" id="listid" />

        </asp:Content>

     

        <script runat="server">

            string breadcrumbListLink = string.Empty;

            string breadcrumbWebLink = string.Empty;

            string listUrl = string.Empty;

            SPList aList = null;

            public void Page_Load(object sender, EventArgs e)

            {

                if (IsPostBack)

                {

                    //provisioning bread crumb

                    using (SPWeb myWeb = SPContext.Current.Web)

                    {

     

                        //get the list ID stored before Postback

                        aList = myWeb.Lists[new Guid(listid.Value)];

                        listUrl = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(myWeb.Url, aList.RootFolder.Url);

                        //server side step to provision the bread crumb.

                        breadcrumbWebLink = "<a href='" + myWeb.Url + "'>" + myWeb.Title + "</a>";

                        breadcrumbListLink = "<a href='" + listUrl + "'>" + aList.Title + "</a>";

                    }

                    return;

                }

     

                using (SPWeb myWeb = SPContext.Current.Web)

                {

                    try

                    {

                        aList = myWeb.Lists[new Guid(Request.QueryString["id"])];

     

                        //provisioning bread crumb

                        listUrl = SPUrlUtility.CombineUrl(myWeb.Url, aList.RootFolder.Url);

                        breadcrumbWebLink = "<a href='" + myWeb.Url + "'>" + myWeb.Title + "</a>";

                        breadcrumbListLink = "<a href='" + listUrl + "'>" + aList.Title + "</a>";

     

                        //storing the list ID to be retrieved after Postback in order to build bread crumb.

                        listid.Value = aList.ID.ToString();

                    }

                    catch

                    {

                        lblItemsToDeleteList.Text = "The list does not exist. Check that the page URL is correct and has not been manually modified.";

                        return;

                    }

                }

            }

     

            protected override void RenderChildren(HtmlTextWriter output)

            {

                LiteralControl myBreadcrumb = new LiteralControl(breadcrumbWebLink + " > " + breadcrumbListLink);

                Master.FindControl("PlaceHolderTitleBreadcrumb").FindControl("ContentMap").Controls.Add(myBreadcrumb);

                base.RenderChildren(output);

            }

        </script>

     



    I have posted the complete page example in CodePlex :

    SharePoint Delete Items of Custom Lists


     

    2 comments:

    Anonymous said...

    Hi,

    wat code u have given that i used for creating my use control.
    but one URl u have given for URLAction.Can you please let me know where i need to write that URLAction thing.

    Thanks in Advance.

    Regards,
    Chanchal

    Marc Charmois said...

    Hi Chanchal,

    Here is three msdn useful links for the custom actions:

    First a good tutorial from msdn:

    How to: Add Actions to the User Interface
    then the refered documentation:

    Custom Action Definitionsand

    Default Custom Action Locations and IDs
    .

    In my post I have used this code for the feature:

    <?xml version="1.0" encoding="utf-8" ?>
    <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
    Id="EDFD6601-66BA-4c73-8928-DC84CE52D8AC"
    Title="Delete List Items"
    Description="Customize List Action menu in order to delete several List items"
    Scope="Web"
    Hidden="false"
    ImageUrl="e-marguerite/marguerite.ico"
    AlwaysForceInstall="TRUE" >
    <ElementManifests>
    <ElementManifest Location="elements.xml"/>
    </ElementManifests>
    </Feature>

    and this one for the elements:

    <?xml version="1.0" encoding="utf-8" ?>
    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
    <CustomAction
    Id="SiteSettings"
    RegistrationType="List"
    RegistrationId="100"
    GroupId="ActionsMenu"
    Location="Microsoft.SharePoint.StandardMenu"
    Sequence="2000"
    Title="Delete Items"
    Description="Delete List items"
    Rights="DeleteListItems"
    >
    <UrlAction Url="~site/_layouts/e-marguerite/delListItems.aspx?id={ListId}"/>
    </CustomAction>
    </Elements>

    You can find the entire project in codeplex at:


    delete list items source codeHope this helps.

    Marc