Category Archives: Windows Presentation Foundation

kick it on DotNetKicks.com

Digg This

Silverlight_Logo_2

This is the first post covering techniques for both sending data into your Silverlight environment from ASP.NET as well as getting data out of Silverlight without resorting to a lot of new elements in your architecture. The goal is to use what you already have with the least fuss.

You may think you need to resort to ‘pushing’ all data from Silverlight into say a service using WCF but that is not the case in many scenarios.

For example, you may have activity which the user creates inside Silverlight 2.0 that results in visual elements you want to send out to ASP.NET for persistence in your ORM environment (where Silverlight has no involvement).

From ASP.NET to Silverlight 2.0

First, let’s quickly review the easiest way to pass information into your Silverlight control.

InitParamaters

Here is the on-line help:

If parameters are included, they are typically in comma-delimited pairs and are available as a dictionary object in a Silverlight 2 startup event. These parameters are not used in a Silverlight 1.0-based application.

If an action on an .aspx page causes a postback to occur, the Silverlight plug-in will start again with its content specified in the Source property. The current value of the InitParameters property is sent to the Silverlight plug-in. This enables you to change the InitParameters property before a postback occurs.

The Silverlight 2 application specified in the Source property can access the initialization parameters specified in the InitParameters property in the StartupEventArgs parameter of the Silverlight Application Startup event.

We will walk through an entire example of this, including some content that will make sense in how we can move data back out of Silverlight 2.0 to ASP.NET.

Code for this Scenario

We will be using a web UserControl (.ascx) as our control in this example, because as you will see, we need more than just the Silverlight control to make this work.

ASCX Host

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SilverlightInt.ascx.cs"
  Inherits="SilverlightInt" %>
<%@ Register Assembly="System.Web.Silverlight"
 Namespace="System.Web.UI.SilverlightControls"
    TagPrefix="asp" %>
<asp:Silverlight ID="SilverlightView" runat="server" 
Source="~/ClientBin/AspNetIntegration.xap"
    MinimumVersion="2.0.31005.0" />
<asp:TextBox ID="SilverOutput" runat="server"  
 Style="display: none"></asp:TextBox>

ASCX Code Behind

    public partial class SilverlightInt : UserControl
    {
        [Browsable(true)]
        public String InitialText { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            SetSilverlightInitParamaters();
        }

        void SetSilverlightInitParamaters()
        {
            // Note: We need the client ID for later...
            var InitParams = new Dictionary<String, String>
                             {
                                 {
                                     "outputcontrol",
                                    SilverOutput.ClientID
                                     },
                                 {
                                     "InitialText",
                               InitialText ?? "Hello World"
                                     }
                             };

            SilverlightView.InitParameters =          
         InitParams.ToSilverlightInit();
        }
    }

You might notice the extension method ToSilverlightInit(). Here is the code:

 public static class SilverlightIntegrationExtensions
    {
        /// <summary>
        /// Parse the dictionary into Silverlight format
        /// for InitParams
        /// </summary>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        public static String ToSilverlightInit(
             this IDictionary<String, String> target)
        {
            if (target == null)
                throw new ArgumentNullException("target");

            var stringBuffer = new StringBuilder();

            foreach(var kvp in target)
            {
                if (stringBuffer.Length > 0)
                    stringBuffer.Append(",");

                // Eliminate case sensitivity
              stringBuffer.Append(kvp.Key.ToLower()
                + "=" + kvp.Value);

            }

            return stringBuffer.ToString();

        }

    }

This is hosted in a normal ASPX page as follows (surrounding detail omitted):

  <form id="form1" runat="server" style="height: 100%;">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <asp:Image Width="300px" ImageUrl="Silverlight_Logo_2.png"
           runat="server" />
        <br />
        <asp:Literal ID="sentText" runat="server" /><br />
        <hr />
        <integrate:SilverlightInt ID="SilverlightInt1"
           runat="server"     InitialText="This is a Test" />
    </div>
    </form>

Here is what it looks like:

image

Silverlight Code for Initialization

 public partial class App : Application
    {
        public App()
        {
            Startup += Application_Startup;
            UnhandledException += Application_UnhandledException;
            InitializeComponent();
        }

        void Application_Startup(object sender, StartupEventArgs e)
        {
            var PassedInArguments = e.InitParams;
            RootVisual = new SilverlightView(PassedInArguments);
        }

The interesting parts are that we are accessing the InitParams off the Startup’s ‘e’ object. This is a Dictionary<String,String> which is what prompted the ASP.NET design.

Also, we do not use a paramaterless constructor on the initial RootVisual. Instead this is the code:

Silverlight View

<UserControl x:Class="AspNetIntegration.SilverlightView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid HorizontalAlignment="Left" VerticalAlignment="Top"
       x:Name="LayoutRoot" Background="Gray">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>

        <TextBlock HorizontalAlignment="Center"       
     VerticalAlignment="Center"
             Grid.Row="0" Text="Inside Silverlight" />
        <TextBox LostFocus="SendResultBackToAspNet" Grid.Row="1"
          BorderThickness="2" BorderBrush="Black"               
  x:Name="initialText"  />

    </Grid>

</UserControl>

Code Behind

public partial class SilverlightView : UserControl
    {
        readonly IDictionary<string, string> _initParamaters;
        string _initialText =               
 "Nothing was Passed In - initialtext was empty";

        public SilverlightView(            
  IDictionary<string, string> passedInArguments)
        {
            _initParamaters = passedInArguments;
            InitializeComponent();
            Loaded += OnLoaded;
        }

        void OnLoaded(object sender, RoutedEventArgs e)
        {
            SetInitialText();
        }

        void SetInitialText() {

            if (_initParamaters.ContainsKey("initialtext"))
            {
                _initialText = _initParamaters["initialtext"];
            }

            initialText.Text = _initialText;
        }

        void SendResultBackToAspNet(object sender, RoutedEventArgs e)
        {

        }
    }

Notice the ‘SendResultBackToAspNet’ is empty.. That is coming next and is the tricky part.

Coming Next

The code will all be available for download and the much more interesting aspect of sending data back the other way will be presented.

Damon