El Blanco's Office 2007 Blog

Thursday, July 03, 2008

Adding a SharePoint Site Picker to a _layouts Page

I've come across this scenario of a few times . . . you're implementing an application page that sets up some configuration for a SharePoint application you're developing. As part of this configuration, you need your end-user to enter a site from the current site collection. You could just put a text box on your _layout page and let them enter the URL to the site, perhaps adding some server-side validation to ensure that the URL the user entered corresponds to an actual site. A more user friendly approach would be to repurpose the SharePoint site picker dialog box that no doubt you have seen in a few places throughout SharePoint configuration settings:

How can you go about doing this ? Well, it's not as hard as you might expect:
  1. Create your _layout page as you normally would, and add two server controls to the .aspx page: a standard ASP.NET text box called txtWebUrl and a standard ASP.NET button contol called btnBrowse.

  2. In the code behind of your _layout page override the OnPreRender method as shown below:

    protected override void OnPreRender(EventArgs e)
    {
        ScriptLink.Register(this.Page,
            "PickerTreeDialog.js", true);
        AddSitePickerControlClientScript();
        base.OnPreRender(e);
    }


  3. The OnPreRender method registers the "PickerTreeDialog" javascript file that ships with MOSS and contains the "LaunchPickerTreeDialog" function. OnPreRender also calls the "AddSitePickerControlClientScript" method that we need to define as shown below:

    private void AddSitePickerControlClientScript()
    {
    string script =
    "var lastSelectedSiteSmtPickerId = null; " +
    "function LaunchSitePicker() " +
    "{ " +
    "if (!document.getElementById) return; " +
    "var siteTextBox = document.getElementById('" +
    SPHttpUtility.EcmaScriptStringLiteralEncode(
    this.txtWebUrl.ClientID) +
    "'); " +
    "if (siteTextBox == null) return; " +
    "var serverUrl = '" +
    SPHttpUtility.EcmaScriptStringLiteralEncode(
    SPContext.Current.Web.ServerRelativeUrl) +
    "'; " +
    "var callback = function(results) " +
    "{ " +
    "if (results == null results[1] == null) return; " +
    "lastSelectedSiteSmtPickerId = results[0]; " +
    "siteTextBox.value = results[1]; " +
    "}; " +
    "LaunchPickerTreeDialog(" +
    "'CbqPickerSelectSiteTitle'," +
    "'CbqPickerSelectSiteText', " +
    "'websOnly','', " +
    "serverUrl, lastSelectedSiteSmtPickerId," +
    "'','','/_layouts/images/smt_icon.gif','', " +
    "callback); " +
    "}"
    ;

        this.Page.ClientScript.RegisterClientScriptBlock(
            typeof(TestPage),
            "LaunchSitePicker",
            script, true);
    }


  4. This method defines a JavaScript function called "LaunchSitePicker". The "LaunchSitePicker" function defines a JavaScript callback function which is used by the site picker dialog when the dialog is closed. In the callback function is code that sets the txtWebUrl text box to contain the URL of the selected site. The "LaunchSitePicker" function then calls the "LaunchPickerTreeDialog" function which is part of "PickerTreeDialog.js" i.e. the file that ships with MOSS that we linked to in the OnPreRender method above.

    The "AddSitePickerControlClientScript" then calls the RegisterClientScriptBlock page method to register the JavaScript function we defined.

  5. The final step is to add the following code in your Page_Load method:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            this.btnBrowse.Attributes.Add(
                "onClick", "LaunchSitePicker()");
        }
    }

  6. This simply adds on onClick attribute to the btnBrowse button so that the "LaunchSitePicker" JavaScript function we defined is called when the button is clicked.

  7. Following all of the above intructions should give you a _layout page that looks like the following:

  8. Clicking on the "Browse…" button will display the site picker allowing you to select the desired site in your site collection. When you close the site picker by clicking the "OK" button the URL of the selected site will be injected into the text box.

Hopefully this will allow you to develop more user-friendly _layout application pages for your applications.

3 Comments:

  • Great post. I was able to use the site picker control in the association form (custom aspx page) of a custom workflow.

    Thanks :)

    Claudia

    By Anonymous Claudia Gil, at 7:46 pm  

  • Thanks for writing such an interesting post.

    By Anonymous rfarqleet, at 8:11 am  

  • Hi, just to mention you have a small issue in your callback function. Your callback function checks the results for null and an item at index 1 however the check should include an || ?

    It wasn't building for me until I made that change. Hope it helps. :-)

    By Blogger Brian, at 10:40 am  

Post a Comment

<< Home