Pass event data from a Silverlight control to a SharePoint page

There are many examples out there of how to pass data from a SharePoint page or web part to a Silverlight control. For example, you could use the an HTML bridge, initParams or even the client object model -see How to pass data to Silverlight control for loads of examples.

However, I could not find an example of how to pass data from Silverlight to SharePoint that also dealt with SP.UI.ModalDialog’s so this post will describe what I came up with.

Note: This post is not about how to fetch data to and from Silverlight via the object model. What I’m attempting to describe here is how an event in a Silverlight control can be used to pass information back to SharePoint via a Modal Dialog.

The example scenario I’m using is a follows: you have a source SharePoint page or web part (blue) that needs to call a Silverlight control to perform some advanced function. The source page wants to open the Silverlight control in an SP.UI.ModalDialog. The target of the modal dialog is another SharePoint page or web part (green). The target page in turn renders the Silverlight control (red).

image

Here are the scenarios I’m trying to answer:

  • How does the Silverlight control close the modal dialog that it is contained within?
  • How does the Silverlight control pass data back to the source page?
    To answer these questions, changes are required to be made to the source page, the target page and the Silverlight control. However, these changes are fairly simple to apply and the results work seamlessly.

    Source page changes

    We need to update the source page to include the necessary JavaScript to open an SP.UI.ModalDialog and to respond to its close event. I’m assuming you’ve got access to the code behind for the source page, if not, all the code shown can be place into a web part that is then placed on the source page or (a version of) the JavaScript can be directly added to the source page.

    First we create a variable to hold the unique name for our source page script:
    // create a unique name for our JavaScript
    string scriptName = "ThrowAModal" + DateTime.Now.Ticks.ToString();

    Next we start a new StringBuilder and write the open tag for our script element:

    // construct the required script contents
    StringBuilder modal = new StringBuilder();
    modal.Append("<script language='javascript' type='text/javascript'>");

    Next we create the JavaScript function that will get called when our ModalDialog is finally closed – this is our CallBack function. In this example I’m testing the results of the dialog (e.g. was it cancelled or closed gracefully) and then I’m displaying the returnValue than will eventually come from the Silverlight control in a notification message. When you see the notification message you’ll know that the Silverlight control has successfully passed data back to the source page:

// this will get called when the modal is closed
#region CallBack Javascript
modal.Append("function " + scriptName + "CallBack(dialogResult, returnValue)");
modal.Append("{");
modal.Append(" alert(dialogResult + ' - ' + returnValue); ");
modal.Append(" if(dialogResult==1) ");
modal.Append("  {");
modal.Append("  var myNotifyId = SP.UI.Notify.addNotification(returnValue, false);");
modal.Append("  }");
modal.Append("}");
#endregion

Next we create the JavaScript that opens our target page in a ModalDialog. What’s important to note here is that were passing into the options for the ModalDialog, the name of our CallBack function we defined above:

// this will open the modal
#region Dialog Javascript
modal.Append("function " + scriptName + "() { ");
modal.Append("var options = { ");
modal.Append("url: '/yourURLhere.aspx', ");
modal.Append("width: 800, ");
modal.Append("height: 500, ");
modal.Append("title: 'Throw a Modal sample', ");
modal.Append("allowMaximize: false, ");
modal.Append("showClose: true, ");
modal.Append("dialogReturnValueCallback: " + scriptName + "CallBack");
modal.Append("};");
modal.Append("SP.UI.ModalDialog.showModalDialog(options); ");
modal.Append("}");

Next we complete our script by actually calling our function that will open the ModalDialog:

// cause the modal to be opened 
modal.Append("ExecuteOrDelayUntilScriptLoaded(" + scriptName + ", \"sp.js\"); ;");
#endregion

Finally, our source page JavaScript is complete so we can close the script block and add the script to the page:

modal.Append("</script>");

// add the script to the page
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), scriptName, modal.ToString());

Target page changes

Now we need to make a minor change to our target page. Again, this could be done in the code behind, in a web part or by adding the JavaScript directly into the page.

First we use a StringBuilder to create our script block:

// construct the required script contents
StringBuilder targetScript = new StringBuilder();
targetScript.Append("<script language='javascript' type='text/javascript'>");

Next we create the function that our Silverlight will be calling and that in turn will close the ModalDialog and pass the results from Silverlight to the source page CallBack function:

// this will be called by Silverlight
#region Invoke Javascript
targetScript.Append("function CancelPressed(results)");
targetScript.Append("{");
// show the data passed out of Silverlight
targetScript.Append(" alert(results);"); 
// close the dialog and return the results
targetScript.Append(" window.frameElement.commonModalDialogClose(1,results);");  
targetScript.Append("}");
#endregion

Notice the above function is called ‘CancelPressed’ we’ll need to reference this script by name in our Silverlight control.

We’re done with the target page scripting so we can close our script block and add the script to our page:

targetScript.Append("</script>");

// add the script to the page
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CancelPressedScript", targetScript.ToString() );

Silverlight control changes

The changes required to be made to the Silverlight control are the simplest of all. On the event you want to use to trigger closing the ModalDialog (and with it the Silverlight control) and pass data back to the source page CallBack function simply add the following code:

private void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e)
{
    // call our target page function
    System.Windows.Browser.HtmlPage.Window.Invoke("CancelPressed", 
        "Hello from Silverlight - cancel has just been pressed.");
}

The System.Windows.Browser.HtmlPage.Window.Invoke method takes two parameters. The first is the name of the script object we wish to call. This needs to be the name of the function you added to the target page. The second parameter is a params object[] array that can be used to send data back to the target page and onto the source page. In this example I’m simply passing a string message but this same technique will work for all primitive data types.

Result

Here the overall process flow the above code helps achieve:

image

I hope this helps…

Advertisements

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: