Wednesday, September 19, 2012

How to pass parameters into a Silverlight Application

After spending some quality time in Colombo SharePoint camp, today I am going to write about how to pass parameters to a Silverlight application. This of course can be really useful even in SharePoint where let's say for an example, a different Silverlight page should be displayed based on the requested page. In such cases generally what comes to our mind is using 2 xaps,  but it is not possible with a Silverlight application, because a single Silverlight application can create only one xap file. So another thing we can do is creating a separate Silverlight application for the other view which is not a good practice.

So the best approach would be passing parameter to the Silverlight application when it is loading. There are variety of ways to achieve it and here, I will be showing only the most used ways.

I have created a Silverlight Application and I have a Web Project to host my Silverlight Application. I will be passing the parameters using following ways.
    1. Adding to Resources
    2. Constructor Overloading
  1. Query String
InitParams

In the Silverlight application, in the App.xaml there is a event which is Application_Startup(object sender, StartupEventArgs e). This will be triggered when an application is started and when the application is starting up Silverlight application Processes initialization retrieved from the InitParams property of the StartupEventArgs object that is passed to the Startup event handler. The initialization parameters are passed as the initParams parameter when you embed the Silverlight plug-in in a Web page like below.
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
          <param name="source" value="ClientBin/SilverlightApplicationParam.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="5.0.61118.0" />
          <param name="autoUpgrade" value="true" />
          <param name="initParams" value="param1=FromInitParams" /> <%--my customer init parameter--%>
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration:none">
               <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
        </object>
        <iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>
    </div>
In here as you can see, I have created a init parameter. The input format of this parameter starts as a single string with individual parameters delimited using a comma (,), and keys delimited from values using an equal sign (=). For example, "key1=value1,key2=value2,key3=value3". The delimiters are processed so that this API can provide them as a dictionary. So I pass multiple parameters like this.
<param name="initParams" value="param1=FromInitParams,param2=FromInitParams2,param3=FromInitParams3" />
So when we pass init params this way, we can consume these from the Application_Startup(object sender, StartupEventArgs e) event in the App.xaml. From that event either we can save this in global resources dictionary for later use or we can overload the initial page constructor and pass to it. Let’s see this in action.

App.xaml
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            var _message = "";

            // way 1
            // save in global resources dictionary 
            if (e.InitParams != null)
            {
                // reading all initparams and adding it to global resources dictionary
                foreach (var item in e.InitParams)
                {
                    this.Resources.Add(item.Key, item.Value);
                }
            }
            this.RootVisual = new MainPage();

            // way 2
            // overload the initial page constructor
            if (e.InitParams != null)
            {
                // check for a specfic key from the initparams
                if (e.InitParams.ContainsKey("param1"))
                {
                    // getting the value of a specific key
                    _message = e.InitParams["param1"];
                }
            }
            // passing parameter to intial page constructor
            this.RootVisual = new MainPage(_message);
        }
MainPage.xaml
        private string _message = "";

        // way 1
        public MainPage()
        {
            InitializeComponent();
            _message = GetParameterValueFromKey("param1");
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        // find the key in global resources dictionary and
        // return the value of it
        private string GetParameterValueFromKey(string key)
        {
            if (Application.Current.Resources[key] != null)
            {
                return Application.Current.Resources[key].ToString();
            }
            else
            {
                return string.Empty;
            }
        }

        // way 2
        public MainPage(string message)
        {
            InitializeComponent();
            _message = message;
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
And in the MainPage_Loaded event I am showing the value in a message box.
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(_message);
        }

Query String

Let’s say I have a button to redirect my page to the page which hosts the Silverlight Application. I am passing some parameter via query string to that page.
        protected void btnSilverlight_Click(object sender, EventArgs e)
        {
            Response.Redirect("~/SilverlightApplicationParamTestPage.aspx?param1=FromQueryString");
        }
I can consume this value from MainPage.xaml in the following way.
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            IDictionary<string, string> qString = HtmlPage.Document.QueryString;
            foreach (KeyValuePair<string, string> keyValuePair in qString)
            {
                if (keyValuePair.Key == "param1")
                    _message = keyValuePair.Value;
            } 
            MessageBox.Show(_message);
        }
So isn't this nice.

Happy Coding.

Regards,
Jaliya

2 comments: