DCSIMG
June 2008 - Posts - Alex Golesh's Blog About Silverlight Development

June 2008 - Posts

Quick Silverlight Tip: Initialization Parameters

The scenario: you developing Silverlight application, and you need to pass some parameter inside - for example to define which page will be shown, or to pass user credentials, after he already logged-in in previous non-Silverlight part of application.

So, ho you could do it? The answer is pretty simple - "initParams" in Silverlight object construction.

The parameters could be named, and not named.

Named parameters example:

<object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
        <param name="source" value="ClientBin/InitParams.xap"/>
        <param name="onerror" value="onSilverlightError" />
        <param name="background" value="white" />
        <param name="initParams" value="UserName=Alex, AuthID=123, eMail=alexg@sela.co.il" />

Non-Name parameters example:

<object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
        <param name="source" value="ClientBin/InitParams.xap"/>
        <param name="onerror" value="onSilverlightError" />
        <param name="background" value="white" />
        <param name="initParams" value="Alex,123,alexg@sela.co.il" />

Once those parameters being passed to application it could be used in code-behind. There is two ways to get those parameters: as a part of StartupEventArgs (in Application_Startup event) or get them directly from Silverlight plug-in.

Here is first way to do it:

//In App.Xaml.cs private void Application_Startup(object sender, StartupEventArgs e) { //In my example, if there is InitParams specified call an overloaded constructor if (e.InitParams.Count > 0) this.RootVisual = new Page(e.InitParams); else this.RootVisual = new Page(); } //In Page.Xaml.cs - somewhere in class:
IDictionary<string, string> initParams;



 

public Page(IDictionary<string, string> parameters) { //do whatever need to be done - for example...
initParams = parameters; }

This approach is good when we use named parameters, because unnamed parameters will return InitParams.Count = 0.

To deal with unnamed parameters, we could get them from plugin properties:

public Page()
{
    InitializeComponent();

    string sParameters = System.Windows.Browser.HtmlPage.Plugin.GetProperty("initParams").ToString();

    //If parameters return
    if (sParameters.Length > 0)
    {
        //Process them....
        string[] parameters = sParameters.Split(new char[] { ',' });

        if (null != parameters)
        {
            //In my case I'm making unnamed parameters behave closely to named parameters
            initParams = new Dictionary<string, string>();
            int counter = 0;

            //I'm adding every value with some genrated key to dictionary collection, 
            //which will enable me to use them exactly like named.
            foreach (var item in parameters)
            {
                string key = "KEY_" + counter;
                string val = item;
                initParams.Add(key, val);

                counter++;
            }
        }
    }

We done... Now we can accept parameters and use it.

 

Enjoy,

Alex

Quick Tip: Silverlight Integration within HTML content

Couple of days ago I've got question, how Silverlight content could been integrated/overlapped by some HTML/AJAX content. The samples I've received produced following behavior -

When clicking on hyperlink, it opens "modal pop-up" but Silverlight control is floating over it:

imageimage

 

Another sample:

When clicking on "Click Here" button HTML "window" being placed behind Silverlight control:

image image

Now the quick tip:

When you need to make layering, positioning, etc. integration of your Silverlight content and HTML content you have to define "Windowless" parameter for Silverlight object:

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/AjaxModal_SL.xap" Width="600px" Height="600px" Windowless="true" />

or

<object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="100%" height="100%">
    <param name="source" value="ClientBin/AjaxModal_SL.xap"/>
    <param name="onerror" value="onSilverlightError" />
    <param name="windowless" value="true" />
    
    <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
    </a>
</object>

Now the samples works fine:

image image

 

Enjoy,

Alex

 

P.S. Thanks to Denis for providing samples

Path.Data Dependency Property Initialization from String - Take 2

Day or to ago, I've blogged how to initialize Path.Data property in Silvelright 2 Beta 2 from string. In this post I've mention, that probably the best and the right way to do it is develop functionality similar to WPF's PathFigureCollectionConverter object.

Now it exists: the porting of PathFigureCollectionConverter functionality for Silverlight 2 Beta 2 in my CodePlex project.

Here is usage sample (just add reference to your project):

XAML
<Path x:Name="path" Canvas.Left="10" Canvas.Top="30" Stroke="Black" Height="200" Width="200"/>

CSharp

PathConverter.StringToPathGeometryConverter conv = new PathConverter.StringToPathGeometryConverter();
PathGeometry pathData = conv.Convert(pathString);

path.SetValue(Path.DataProperty, pathData);

The result (path string was "M 16.749,115.917C 16.749,85.5106 58.2626,70.0341 84.4816,68.9416C 110.701,67.8491 136.028,70.1342 147.844,76.0426C 153.853,79.0469 154.945,80.9587 154.945,84.2361C 154.945,86.5613 155.331,122.651 155.331,141.146C 155.331,148.698 152.989,150.416 150.029,151.514C 138.741,155.701 16.749,201.04 16.749,115.917 Z"):

image

All binaries, sources and samples at CodePlex.

If you like it - vote for this in CodePlex.

Next step is to implement IValueConverter to allow usage of this library for binding... Stay tuned!

Update: IValueConverter & Convert-Back-To-String implemented. Get updated code/binaries/samples here.

Update 2: Support for FillRules syntax added. Updated code/binaries here.

 

Enjoy,

Alex

Path.Data Dependency Property Initialization From String

In Silverlight 2 Beta 1 I used to build dynamic UI with drawing portions.

For example, I used to draw Path dynamically like in following example:

Path myPath = new Path();
myPath.SetValue(Path.DataProperty, "M 50,50 L 50,100 L 100,100 L 100,50 L 50,50 Z");
myPath.SetValue(Path.NameProperty, "myPath");
myPath.Width = 100;
myPath.Height = 100;
myPath.Fill = new SolidColorBrush(Colors.Black);
LayoutRoot.Children.Add(myPath);

This gave me nice rectangle... Everything was fine, until I start to port my project to Silverlight 2 Beta 2. After fixing all known stuff, I finally executed the application and in the moment I expected to get some nice Path being drawn I've got exception:

image

What happened? Why? It used to work before... Well, the answer is in changes documentation for Beta 2:

 

SetValue Only Accepts the Correct Types (No Conversions)
Who Is Affected: Silverilght 2 Beta 1 managed applications using SetValue.
Summary and Fix Required
SetValue will only accept the correct types for the given DependencyProperty. For example, if the dependency property Canvas.LeftProperty is of type System.Double, you must supply an object of type System.Double. Conversions will no longer be done. The following is another example:

Beta 1
[C#]
ellipse.SetValue(Ellipse.StrokeProperty, "Black");

Beta 2
[C#]
ellipse.SetValue(Ellipse.StrokeProperty, new SolidColorBrush(Colors.Black));
In Beta 1, the string "Black" would be converted to a SolidColorBrush of color Black automatically.  In Beta 2, you must pass in an object of type SolidColorBrush.

Well... How we can do it now? The first way, is to prepare PathGeometry object (probably best, but defiantly not the simple and short way to do it) and set it as DataProperty:

PathGeometry p = new PathGeometry();
//Initialize PathGeometry here
//.....
//.....
//
myPath.SetValue(Path.DataProperty, p);

Another alternative is to develop some functionality, which will mimic WPF's PathFigureCollectionConverter (which is missing in Silverlight)... Well, it is also no so simple task...

 

Last alternative is to initialize Path object from string with XamlReader.Load functionality:

string pathXaml = "<Path xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" Data=\"M 50,50 L 50,100 L 100,100 L 100,50 L 50,50 Z\"/>";
Path path = (Path)System.Windows.Markup.XamlReader.Load(pathXaml);
myPath.SetValue(Path.NameProperty, "myPath");
myPath.Width = 100;
myPath.Height = 100;
myPath.Fill = new SolidColorBrush(Colors.Black);
LayoutRoot.Children.Add(myPath);

And it actually works:

image

Mission accomplished... Path object being initialized from string with minimum changes...

 

Enjoy,

Alex

Quick Tip: Isolated Storage in Silverlight 2 Beta 2

One of changes in new Silverlight 2 Beta 2, is new "Silverlight Configuration" screen.

image

 

Now we can take control over DRM and Application Storage. Application storage screen controls isolated storage data and quotas for application being used it:

image 

But what could be stored in this storage? What if default quota (1Mb) is not enough? Could it been changed?

 

The isolated storage could store files and application settings. Working with isolated storage is pretty much like with file system:

First of all we need to get IsolatedStorage for application:

var store = IsolatedStorageFile.GetUserStoreForApplication()

Then, we could use it to create directories, subdirectories, files, etc.

store.CreateDirectory("MyApp1");
string subdirectory1 = System.IO.Path.Combine("MyApp1", "SubDir1");
store.CreateDirectory(subdirectory1);
IsolatedStorageFileStream rootFile = store.CreateFile("InTheRoot.txt");
rootFile.Close();

//Write to text file
string filePath = System.IO.Path.Combine(subdirectory1, "MyApp1A.txt");
try
{
   using (StreamWriter sw =
            new StreamWriter(store.OpenFile(filePath,
            FileMode.Open, FileAccess.Write)))
            {
                sw.WriteLine("To do list:");
                sw.WriteLine("1. Buy supplies.");
             }
}
catch (IsolatedStorageException ex)
{

    sb.AppendLine(ex.Message);
}

//Read from text file
try
{
    using (StreamReader reader =
        new StreamReader(store.OpenFile(filePath,
            FileMode.Open, FileAccess.Read)))
    {
        string contents = reader.ReadToEnd();
        sb.AppendLine(filePath + " contents:");
        sb.AppendLine(contents);
    }
}
catch (IsolatedStorageException ex)
{

    sb.AppendLine(ex.Message);
}

 

To use Isolated storage as application data store, we need to get IsolatedStorageSettings.ApplicationSettings:

private IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;

Now we can use it to add/change/read/delete our applciation settings:

//Add new appSetting
appSettings.Add("email", "alexg@sela.co.il");
//Read appSetting
string mailAddress = (string)appSettings["email"];
//Change existing appSetting
appSettings["email"] = "alex@somemail.com";
//and finally delete it...
appSettings.Remove("email");

Another nice feature, is ability to increase Isolated Storage quota for application. To do it, we need to execute IncreaseQuotaTo() function. While trying to increase the Quota, user will get prompt, which need to be either approved or declined by him:

image

Here the code goes:

using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
    // Request 5MB more space in bytes.
    Int64 spaceToAdd = 5242880;
    Int64 curAvail = store.AvailableFreeSpace;

    // If available space is less than
    // what is requested, try to increase.
    if (curAvail < spaceToAdd)
    {

        // Request more quota space.
        if (!store.IncreaseQuotaTo(store.Quota + spaceToAdd))
        {
            // The user clicked NO to the
            // host's prompt to approve the quota increase.
            tbResults.Text = "User declined to approve Quota inrease";
        }
        else
        {
            // The user clicked YES to the
            // host's prompt to approve the quota increase.
            tbResults.Text = "Quota inreased";
        }
    }
}

 

Sample application could be found here.

Silverlight 2 Beta 2 links here.

 

Enjoy,

Alex

Silverlight 2 Beta 2 available

As was announced earlier this week at TechEd 2008 in Orlando, new Beta 2 for Silverligth 2 has arrived!

Here download links:

Runtime only

Silverlight 2 Beta 2 Tools for Visual Studio 2008 (includes Silverlight SDK, Developers runtime, project templates in single chained installation)

Belnd 2.5 June preview

Deep Zoom Composer Beta 2

Many samples and tutorial videos here

 

Enjoy,

Alex

My WDC Presentation

Yesterday (1 June 2008) I did a Silverlight overview at local WDC (Web Developers Community) monthly meeting.

Thanks for all participants!

Presentation slides could be found here.

Democode here (basics) and here (media player, source code only. Video file will be posted later because of its size).

 

Enjoy,

Alex