Sunday, August 11, 2013

Get selected list / document items from SharePoint Ribbon

In this post we are going to see how we can get selected list / document items from our customized ribbon control.

We may have a requirement to process multiple selected items and then take user to another page for further processing or process the items on another page and then show some messages to the user based on the processing statuses.

If you have not gone through the series of customizing Ribbon from SharePoint Kings, I would recommend you reading the entire series first and then continue reading from here on.

We are going to take an example of document library.

First open up the project and add the empty element file to the project.

Pay proper attention to what we are doing in this element file. 

<?xml version="1.0" encoding="utf-8"?> <Elements > <CustomAction Id="NewItemCustomization" Location="CommandUI.Ribbon" RegistrationId="101" RegistrationType="List" Title="New Item Customization"> <CommandUIExtension> <CommandUIDefinitions> <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children"> <Button Id="ListItemButton" Image16by16="/_layouts/images/CustomImages/Select16.png" Image32by32="/_layouts/images/CustomImages/Select32.png" Command="ListItemCommand" Description="Process Selected List Items" LabelText="Process List Items" TemplateAlias="o2" Sequence="81"/> </CommandUIDefinition> </CommandUIDefinitions> <CommandUIHandlers> <CommandUIHandler Command="ListItemCommand" CommandAction="[removed]avascript: function dialogCallback(dialogResult, returnValue){ SP.UI.Notify.addNotification(returnValue); SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK); } var selectedItems = SP.ListOperation.Selection.getSelectedItems(); var selectedItemIds = ''; var selectedItemIndex; for (selectedItemIndex in selectedItems){ selectedItemIds += '|' + selectedItems[selectedItemIndex].id; } var dialogOptions = { url: '/sites/SharePointSite/_layouts/MetadataSiteColumn/ProcessSelectedDocuments.aspx?selectedItems=' +selectedItemIds +'&ListId=' +SP.ListOperation.Selection.getSelectedList(), title: 'Set Document Prefix', allowMaximize: false, showClose: false, width:500, height:400, dialogReturnValueCallback: dialogCallback }; SP.UI.ModalDialog.showModalDialog(dialogOptions);" /> </CommandUIHandlers> </CommandUIExtension> </CustomAction> </Elements>


First we are targeting our customization to the manage group in the document selection under documents tab. Hence we have taken up Ribbon.Documents.Manage.Controls._children as location.

Next we have defined the button with 16 by 16 image and the image is placed under the layouts folder. We have chosen the default alias for template and a sequence number.


This will give us a result like this.


The important action here is what happens when the button is clicked.

We have define the entire JavaScript inside the element file itself.

In that first we have defined one function.

function dialogCallback(dialogResult, returnValue){
          SP.UI.Notify.addNotification(returnValue);
          SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
        }

This will make sure that when we get a result back from the application page which we will built shortly we display a message as a part of notification as well as we refresh the parent page.

then we take the selected documents. The procedure is same also for the list items. We need to use SP.ListOperations.Selection and then call getSelectedItems() to get all the selected items.

Once we get the items we need to separate them by some separator.  So in this example, we have taken pipeline character. We will then process this items and split them in application page code.

var selectedItems = SP.ListOperation.Selection.getSelectedItems();
        var selectedItemIds = '';
        var selectedItemIndex;
        for (selectedItemIndex in selectedItems){
          selectedItemIds += '|' + selectedItems[selectedItemIndex].id;
        }

Then we are actually opening up an application page and pass on the selecteditems string that we built in prior function. we are also registering the dialogue call back function which is the first function in our code which will refresh the parent page and shows a message as a part of notification.

another point to observe we also get the list name from another method called getSelectedList.

   var dialogOptions = {
          url: '/sites/SharePointSite/_layouts/MetadataSiteColumn/ProcessSelectedDocuments.aspx?selectedItems='
          +selectedItemIds +'&ListId=' +SP.ListOperation.Selection.getSelectedList(),
          title: 'Set Document Prefix',
          allowMaximize: false,
          showClose: false,
          width:500,
          height:400,
          dialogReturnValueCallback: dialogCallback
        };

So far so good. Time to create one application page. Right click your project and then add application page as new item.

So in application page code behind, we will first take a List object of type list items and then we will add to this object our list items that we get from query string. We will bind them to a classic datalist control of asp.net. But we will make sure that we do it in inputformsection.

In another Input form section we then have one textbox on the application page. What we are planning to do is we will ask user to enter document prefix and then we will process our documents and add a prefix to them.

We will have button section and a button which will does this processing of adding prefix to the documents.
Finally we will have a method which will do a magic trick of adding a method called ExecuteOrDelayUntilScriptLoaded to the additional page head of master page and register the method which will close the application page with commonModalDialogClose method.

Here is the class code

public partial class ProcessSelectedDocuments : LayoutsPageBase { List<SPListItem> _selectedListItems = new List<SPListItem>(); protected override void OnLoad(EventArgs e) { // Get all the selected documents. string ListGUID = Request.QueryString["ListId"]; SPList selectedDocumentLibrary = SPContext.Current.Web.Lists[new Guid( ListGUID )]; string[] selectedItems = Request.QueryString["selectedItems"].ToString().Split('|'); for (int index = 1; index < selectedItems.Length; index++) { _selectedListItems.Add( selectedDocumentLibrary.GetItemById( int.Parse(selectedItems[index])) ); } // Bind to the repeater. SelectedDocumentsDataList.DataSource = _selectedListItems; SelectedDocumentsDataList.DataBind(); } protected void OnClickSetPrefixButton(object sender, EventArgs e) { foreach (SPListItem listItem in _selectedListItems) { listItem["Name"] = DocumentPrefixTextBox.Text + " " + listItem.File.Name; listItem.Update(); } CloseDialogOnSuccess(); } private void CloseDialogOnSuccess() { ContentPlaceHolder pageHead = this.Master.FindControl("PlaceHolderAdditionalPageHead") as ContentPlaceHolder; if (pageHead != null) pageHead.Controls.Add( new LiteralControl("[removed]ExecuteOrDelayUntilScriptLoaded(closeDialog,'sp.js');function closeDialog(){ SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Prefix assigned to selected documents.');}[removed]")); } }

 and here is the application page aspx

 <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ProcessSelectedDocuments.aspx.cs" Inherits="MetadataSiteColumn.Layouts.MetadataSiteColumn.ProcessSelectedDocuments" DynamicMasterPageFile="~masterurl/default.master" %> <%@ Register TagPrefix="wssuc" TagName="InputFormSection" Src="~/_controltemplates/InputFormSection.ascx" %> <%@ Register TagPrefix="wssuc" TagName="InputFormControl" src="~/_controltemplates/InputFormControl.ascx" %> <%@ Register TagPrefix="wssuc" TagName="ButtonSection" Src="~/_controltemplates/ButtonSection.ascx" %> <asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server"> </asp:Content> <asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server"> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tr> <td> <wssuc:InputFormSection runat="server" Title="Selected Documents" Description="The following documents have been selected to have the specified prefix added to their titles."> <Template_InputFormControls> <tr> <td> <asp:DataList ID="SelectedDocumentsDataList" runat="server" RepeatColumns="2" CellPadding="2" CellSpacing="5"> <ItemTemplate><li><%# DataBinder.Eval&#40;Container.DataItem, "File.Name"&#41;.ToString()%></li></ItemTemplate> </asp:DataList> </td> </tr> </Template_InputFormControls> </wssuc:InputFormSection> <wssuc:InputFormSection runat="server" Title="Document Prefix" Description="Prefix to add to the selected document titles."> <Template_InputFormControls> <wssuc:InputFormControl LabelText="Prefix to add to the selected documents:" runat="server"> <Template_control> <asp:TextBox ID="DocumentPrefixTextBox" runat="server" /> </Template_control> </wssuc:InputFormControl> </Template_InputFormControls> </wssuc:InputFormSection> <wssuc:ButtonSection runat="server" ShowStandardCancelButton="FALSE" TopButtons="TRUE"> <Template_Buttons> <asp:Button ID="SetPrefixButton" class="ms-ButtonHeightWidth" runat="server" Text="Set Prefix"> <asp:Button ID="CancelButton" class="ms-ButtonHeightWidth" runat="server" Text="Cancel"> </Template_Buttons> </wssuc:ButtonSection> </td> </tr> </table> </asp:Content> <asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server"> Application Page </asp:Content> <asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" > My Application Page </asp:Content>

Time to deploy the application and test it.

Once the solution is deployed, open up a document library. Select couple of documents as shown in image below.


Click on process list items button.

It will show up the selected documents name and a textbox to enter the text that will be appended as a prefix.

I entered test and click on ok on model dialog application page. The model application page closes and a notification is shown on parent page and finally prefix gets applied.

I hope this helps.

No comments:




Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com