Karine Bosch’s Blog

On SharePoint

Creating SharePoint-like Custom Dialogs


When working with SharePoint you certainly configured a Content Query Web Part. Never wished that you could reuse this dialog from within your code?

When copying a document from a document library to another destination in the SharePoint site, never wished you could browse to the destination instead of typing in the complete URL?
 

When taking a closer look at the source code of the Content Query Web Part, you will see that the HTML button calls a JavaScript function named mso_LaunchListSmtPicker().
 
The JavaScript function is defined in the same source file. It gets a reference to a TextBox, defines a callback function to which the results of the dialog should return, and finally calls the LaunchPickerTreeDialog() function. You can pass along arguments like the URL to the dialog, the dialog title, description, icon and the previously defined callback function.


 
The LaunchPickerTreeDialog() function is defined in the PickerTreeDialog.js file that is located in the 12\TEMPLATE\LAYOUTS\1033 directory. This function on its turn calls the commonShowModalDialog function, passing through the arguments like URL to the dialog, the size of the dialog and the callback function. The dialogUrl argument is a concatination of the URL of the dialog, completed with query string parameters for the dialog title, the description, the icon,…

commonShowModalDialog(dialogUrl, PickerTreeDlgDimension, callback, null);

You can reuse the complete functionality of the CQWP dialog using the LaunchPickerTreeDialog() function but there will be cases that this dialog is too restrictive. In that case you can build your own custom SharePoint-like dialogs.
The sample code contains a demo application page that calls a custom dialog when browse button is clicked.

 
You can download the sample code here. It comes with an install.bat that you can use to deploy the solution.

Project structure

This is the project structure:

Developing the dialog

The dialog itself is an .aspx page that inherits from UnsecuredLayoutsPageBase. It applies the dialog.master.  It is in fact a special type of SharePoint application page. The demo itself the dialog page has a code behind class. This code behind will populate the TreeView with lists and document libraries, and their folders.

<%@ Page Language="C#" Inherits="BPoint.SharePoint.ApplicationPages.DemoDialog" MasterPageFile="~/_layouts/dialog.master"     %>

This type of application pages that build upon the dialog.master have some special content place holders. The content place holder for the PlaceHolderAdditionalPageHead contains two ScriptLink controls: one that references the core.js JavaScript file and one that references the PickerTreeDialog.js file.
It also contains a piece of JavaScript that validates the user selection and returns the results to the callback function defined in the calling application page.

<asp:Content ID="Content2" contentplaceholderid="PlaceHolderAdditionalPageHead" runat="server">
 <SharePoint:ScriptLink ID="ScriptLink1" language="javascript" name="core.js" runat="server" />
 <SharePoint:ScriptLink ID="ScriptLink2" language="javascript" name="PickerTreeDialog.js" runat="server" />

  <script type="text/javascript" Language="javascript">
      function ValidateAndReturn() {
          var strDlgReturnValue = new Array(1);
          strDlgReturnValue[0] = "<%= SelectedUrl.Value %>";
          var strDlgReturnErr = "<%= smtPickerError.Value %>";
          if (strDlgReturnValue[0] == null || strDlgReturnValue[0].length <= 0) {
              alert("Please, select a list or folder from the treeview before clicking the OK button");
          }
          else {
              return HandleOkReturnValues(strDlgReturnValue, strDlgReturnErr);
          }
      }
 </script>
 <SharePoint:FormDigest ID="FormDigest1" runat=server/>
</asp:Content>

Another content control is the one that references the PlaceHolderDialogBodyMainSection place holder. It contains two hidden fields: one will contain the URL to the selected list, document library or folder, and one for an eventual error message. It also contains the ASP.NET TreeView control that will be populated when the dialog loads.

<asp:Content ID="Content6" contentplaceholderid="PlaceHolderDialogBodyMainSection" runat="server">
  <DIV ID="HiddenFields" >
    <asp:HiddenField ID="SelectedUrl" Value="" runat="server" />
    <asp:HiddenField ID="smtPickerError" Value="" runat="server"/>
  </DIV>
  <DIV>
      <asp:TreeView ID="WebTreeview" runat="server" OnSelectedNodeChanged="WebTreeview_SelectedNodeChanged" ExpandDepth="1" ShowExpandCollapse="true" ShowLines="true">
          <NodeStyle HorizontalPadding="5" ForeColor="#666666" font-name="Tahoma" font-size="8pt"/>
          <SelectedNodeStyle BackColor="0x000080" ForeColor="0xFFFFFF" />
      </asp:TreeView>
   </DIV>
</asp:Content>

 

Calling the dialog from within an application page

The demo page is a normal SharePoint application pages inheriting from the LayoutsPageBase class. This page has no code behind. It contains an InputFormSection control that displays a TextBox control and a Browse button.  It also contains some JavaScript that is called when a user clicks the Browse button.
This function does the following:
– gets a reference to the TextBox control,
– defines a callback that will display the selected destination in the TextBox
– defines the URL to the dialog page
– defines the location of the image that need to be displayed in the dialog header
– builds the URL for the dialog page, adding query string parameters
– and finally calls the commonShowModalDialog function in the  PickerTreeDialog.js file.

<script type="text/javascript">
    function launchPicker() {
    var textboxId = "<%SPHttpUtility.NoEncode(URLTextBox.ClientID,Response.Output);%>";
    var textbox = document.getElementById(textboxId);
    var webUrl = <%SPHttpUtility.AddQuote(SPHttpUtility.EcmaScriptStringLiteralEncode(SPContext.Current.Web.Url),Response.Output); %>;
        var callback = function(results) {
            if (results == null || results == undefined)
                return;

                var textbox = document.getElementById(textboxId);
                textbox.value = webUrl + results[0];
        }
        var listId = "";
        var PickerTreeDlgUrl= "/_layouts/BPoint Application Page with Dialog/DemoDialog.aspx";
        var iconUrl="/_layouts/images/BPoint/BPoint.PNG";
        var dialogUrl= TrimLastSlash(webUrl) + PickerTreeDlgUrl+"?title=Copy To&page=<%SPHttpUtility.NoEncode(ListID,Response.Output);%>&iconUrl=" + iconUrl;
        var PickerTreeDlgDimension= "resizable:yes;status:no;location:no;menubar:no;help:no";
        commonShowModalDialog(dialogUrl, PickerTreeDlgDimension, callback, null);
}
function TrimLastSlash(siteUrl)
{
 return (siteUrl.charAt(siteUrl.length - 1)=="/")? siteUrl.substring(0,(siteUrl.length - 1)) : siteUrl;
}

 The possibility of developing your own custom dialogs and making them look as out of the box Sharepoint dialogs, opens a wide range of possibilities. You could even host a Silverlight application within such a dialog.

March 21, 2010 - Posted by | SharePoint 2007

17 Comments »

  1. Nice control.

    Unfortunately I am not able to run your code in my system. I would like to know few more information on this.

    1. Can I use this control in a ASP.NET web application, without having share point?

    2. What the advantages of this pop-up, compared to normal Popups? What are the differences bet the tow?

    Regards,
    Pradeep.

    Comment by Pradeep | April 20, 2010 | Reply

  2. Hi Pradeep,

    1. No, I don’t think so: the dialog uses javascript functions that are used/deployed by SharePoint.

    2. When working with SharePoint, it is a lot less code because you rely on and extend what already exists.

    Karine

    Comment by Karine Bosch | April 20, 2010 | Reply

  3. Hi Karine ,
    Thanks a lot for this post this is a very helpful control for me and it’ll save me a lot of time.
    But kindly could u tell me how to deploy the sample code to see how it works on a local sharepoint site of mine?

    Thanks & Regdards

    Comment by Omnia | July 14, 2010 | Reply

  4. I’m cabable now to do something similar to ur solution but do u have any idea if i want to select files not only lists and folders?

    Thanks

    Comment by Omnia | July 18, 2010 | Reply

  5. thanks for information

    Comment by bosch servis | July 21, 2010 | Reply

  6. Hi Omnia,
    If you download the source code you will see that there is some code behind (DemoDialog.aspx.cs). This code is responsible for building the treeview. You can easily add the necessary code to also show the files in the treeview.
    Karine

    Comment by Karine Bosch | July 24, 2010 | Reply

  7. Karine, thank-you for the wonderful post, but I see that you are adding it to the layout of a page, which we asa developers can manipulate from VS or SharePoint designer. What I would like to know is if you have been able to find out how one can create a web part and have one of the custom properties of the web part be associated with the Launchpickertreedialog and have the result from the dialog populate the textbox for the custom property. For example I have a property like the following …

    _
    _
    _
    _
    _
    _
    Public Property Tab1ListName() As String
    Get
    Return _Tab1ListName
    End Get
    Set(ByVal value As String)
    _Tab1ListName = value
    End Set
    End Property

    So when the user is editing the web part, while in the a SP site, they would have access to the picker for selecting the List or Site url that they would normally have to type in for this property if the picker was not available.

    Comment by Kyle Channing | July 28, 2010 | Reply

  8. Hi Kyle,
    Thanks for your interesting question. I have a terrible busy day today (last day before holliday🙂 ) but I’ll try to find out tomorrow or on Saturday.
    Karine

    Comment by Karine Bosch | July 29, 2010 | Reply

  9. […] This all would not have been possible without the help of Karine Bosch’s Post on Custom Dialogs. […]

    Pingback by Sharepoint 2010 RTE Image Picker for the Ribbon | sharepoint services | July 29, 2010 | Reply

  10. With Kyle’s requested enhancement, this is just what I am looking for. However I am looking to have it in Sharepoint 2010 Foundation. Do you have any suggestions on (1) implementing Kyle’s enhancment and (2) doing this in SPF 2010?

    Comment by Rick | September 17, 2010 | Reply

  11. Hi Karine,

    Thank you for a very helpful article.

    I was wondering if this approach will work for WSS 3.0. At first I thought it would not, because of the PickerTreeDialog.js. You know that it comes with MOSS only, not with WSS.
    But then I saw that actually, commonShowModalDialog() from core.js is used. So I removed a scriptlink to PickerTreeDialog.js, and it worked on WSS. Well, almost. An error occured after clicking the OK button in the dialog.
    I found that it is caused by ValidateAndReturn() function that calls HandleOkReturnValues() from PickerTreeDialog.js. The latter function is not very complex, it just checks the return value for errors and displays alerts or saves the result.
    So when I replaced this function with my own which does roughly the same, it worked with WSS 3.0.

    Thanks and Best Regards,
    Deema

    Comment by Deema | October 26, 2010 | Reply

    • Thanks. With your comment I was able to port this to WSS 3.0.

      Comment by awaiK | March 8, 2011 | Reply

  12. Thank you for sharing admin

    service

    Comment by teknikservis | January 31, 2011 | Reply

  13. Thanks. Your post save my day.

    Comment by awaiK | March 8, 2011 | Reply

  14. what is ListID in
    SPHttpUtility.NoEncode(ListID,Response.Output)
    Please let me know about this

    Comment by Sridhar | August 16, 2011 | Reply

  15. Sridhar, good remark. If you download the source code you’ll see that the ListID is a property defined in DemoPage.aspx. In the original version of the dialog it was used in code behind to test upon what to show in the treeview of the dialog page. But this dialog page is a simplified version and is of no use here.

    Comment by Karine Bosch | August 16, 2011 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: