Page view counter

Silverlight DLLs on the desktop CLR

I’m a dinosaur and it’s possible I’m the only who didn’t know this – But you can use Silverlight DLLs on the full .Net desktop CLR.

See, I’ve been working with Silverlight since Mix07 (March 2007) when we were all excited about Silverlight 1.0 and Silverlight 1.1. 
First I was working as a senior .Net consultant on a variety of projects, and for the last 6 months I’ve been working on the Silverlight Toolkit for the evil empire Microsoft. 

So believe me when I say – I’m an aging dinosaur to miss something this big. In Silverlight 2.0 you can share DLLs between the desktop and the Silverlight CLR.
I know for sure it wasn’t possible in Silverlight 1.1, and just assumed it wasn’t possible in Silverlight 2.

From all the articles I’ve read in the last few months, It seems I’m not the only one who doesn’t know this:
http://pagebrooks.com/archive/2008/10/11/sharing-code-between-.net-and-silverlight-platforms.aspx
http://petesbloggerama.blogspot.com/2008/12/referencing-non-silverlight-assembly-in.html
http://stackoverflow.com/questions/208123/what-is-the-best-practice-for-compiling-silverlight-and-wpf-in-one-project

All of these fairly recent articles say the same – You need to use the “Add as link” hackery to share source between Silverlight CLR and the full .Net CLR.

image

Well, Apparently that’s not true. You can add a reference from a full .Net CLR to a Silverlight assembly.

 

Let’s see how to do that:

1. Let’s start a new Silverlight Application:
image

Here’s the Solution we got:

image

2. Let’s add a Silverlight Class Library to hold our Business logic.

image

Here’s our solution now:

image

3. Let’s add a class with some business logic.

public class Person

{

    private string _firstName;

    public string FirstName

    {

        get { return _firstName; }

        set { _firstName = UpperCaseFirstLetter(value); }

    }

 

    private string _lastName;

    public string LastName

    {

        get { return _lastName; }

        set { _lastName = UpperCaseFirstLetter(value); }

    }

 

    private string UpperCaseFirstLetter(string str)

    {

        if (string.IsNullOrEmpty(str) || str.Length == 0)

            return str;

 

        return str[0].ToString().ToUpper() + str.Substring(1, str.Length - 1);

    }

 

    public string FullName

    {

        get

        {

            return string.Format("{0} {1}", FirstName, LastName);

        }

    }

}

This class has 3 interesting things in it:

  1. It has 2 properties called “FirstName” and “LastName” that have a backing field.
  2. When setting the First and last name, we store these with the first character as uppercase. Property setter business logic.
  3. We have a property that combines that value of the first two properties. Pure business logic.

 

4. We’ll add a new WPF project that runs of the desktop .Net CLR. (We could have used the ASP.Net project already in the solution, but I’d like to demo WPF)

image

5. Now, we’ll add a reference from the WPF project to the Silverlight Class Library.

image

image

image

 

Using the Business logic in the Silverlight application

First, I’ll add a reference from the Silverlight Application to the Silverlight Class Library.

image

Next, I’ll add a reference to the Silverlight Toolkit (http://codeplex.com/Silverlight) mainly because we need the WrapPanel.

image

Next, we’ll add this little form to our default page:

<Border x:Name="LayoutRoot" Background="White" Margin="20" CornerRadius="5" BorderBrush="LightGray" BorderThickness="1" >

    <controls:WrapPanel Width="150" >

        <TextBlock Width="75" Text="First Name:" />

        <TextBox Width="75" Text="{Binding FirstName, Mode=TwoWay}" TabIndex="1" />

        <TextBlock Width="75" Text="Last Name:" />

        <TextBox Width="75" Text="{Binding LastName, Mode=TwoWay}" TabIndex="2" />

        <TextBlock Width="75" Text="Full Name:" />

        <TextBox Width="75" x:Name="txtFullName" IsReadOnly="True" InputMethod.IsInputMethodEnabled="False" />

        <Button Content="Update full name" Click="Button_Click" />

    </controls:WrapPanel>

</Border>

This might look lie a lot, but it’s really not.
It’ just the following form:

image

It’s only 3 textblocks, 2 editable textboxes, 1 readonly TextBox and a button.

Now let’s add some code to our code behind:

using BL;

 

namespace SilverlightApp

{

    public partial class Page : UserControl

    {

        public Page()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            this.DataContext = new Person();

        }

 

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            txtFullName.Text = ((Person) this.DataContext).FullName;

        }

    }

}

Basically, we set the DataContext for the whole form to a Person class and once the button is clicked we manually update the txtFullName.
We could have used Dependency Properties to update this for us, but I’d rather keep this demo simple :)

 

If we run our application we’ll see the following form:

image

We’ll put a very sexy and rugged first name and last name.

image

Next we’ll click the Update button:

image

Well, that’s pretty straight forward Silverlight. (And if we added Dependency Properties it would have been much better, but this isn’t a Silverlight demo)

 

 

Using the Silverlight Class Library / Business Logic in the WPF application

We’ll create a similar yet not identical version of the form in WPF:

<Window x:Class="WPFApp.Window1"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Title="Window1" Height="300" Width="300">

    <Grid>

        <WrapPanel Width="150" >

            <TextBlock Width="75" Text="First Name:" />

            <TextBox Width="75" Text="{Binding FirstName}" TabIndex="1" />

            <TextBlock Width="75" Text="Last Name:" />

            <TextBox Width="75" Text="{Binding LastName}" TabIndex="2" />

            <TextBlock Width="75" Text="Full Name:" />

            <TextBox Width="75" x:Name="txtFullName" IsReadOnly="True" InputMethod.IsInputMethodEnabled="False" />

            <Button Content="Update Full Name" Click="Button_Click" />

        </WrapPanel>

    </Grid>

</Window>

And here’s the pretty almost identical code behind:

using BL;

 

namespace WPFApp

{

    public partial class Window1 : Window

    {

        public Window1()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Window1_Loaded);

        }

 

        void Window1_Loaded(object sender, RoutedEventArgs e)

        {

            this.DataContext = new Person();

        }

 

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            txtFullName.Text = ((Person) this.DataContext).FullName;

        }

    }

}

Let’s run this app.

image

We’ll put in the ruggedly manly name we used before.

image

Click the update button.

 

image

And yep, the same result – the Silverlight code runs on both the desktop CLR and the SIlverlight CLR.

 

One picture is worth an entire blog post

image

 

How does this even work? 

The System.String from Silverlight is a completely different System.String from the desktop .Net. So how does this even work? I’m still looking into this, but before I got the results of my research I thought it’s definitely worth sharing.

 

This has limitations, probably a lot

Using the full abilities of the Silverlight runtime is obviously not possible from our Silverlight class library when it runs on the desktop. There’s no Application.Current, no dispatcher and a host of other things are missing. This limit us to really sharing only business logic in this method, not UI.
For one, I’m not sure it’s not a good thing that we’re being forced to keep best practices of layer separation.

 

Source code available at: http://silverlight.net/blogs/justinangel/BlogStorage/SharingCode.zip

 

-- Justin Angel

Microsoft Silverlight Toolkit Program Manager

Published Monday, December 29, 2008 8:34 PM by JustinAngel
Filed under:

Comments

# Silverlight DLLs on the desktop CLR - Justin myJustin = new Microsoft.Silverlight.Justin();

Pingback from  Silverlight DLLs on the desktop CLR - Justin myJustin = new Microsoft.Silverlight.Justin();

# re: Silverlight DLLs on the desktop CLR

Wow! U da man Justin! Thanks bro.

Tuesday, December 30, 2008 6:42 AM by wisecarver

# re: Silverlight DLLs on the desktop CLR

Justin,

Thanks for this, it also works the other way somewhat, as I discovered while trying to call an F# class library inside a Silverlight app:

www.bluerosegames.com/.../Embedding-a-F-class-library-in-a-Silverlight-2-Application.aspx

I was able to include a .Net assembly in my XAP file, I'm sure there are limitations there as well.

Tuesday, December 30, 2008 7:42 AM by Bill Reiss

# Silverlight Cream for December 30, 2008 -- #471

In this issue: Pete Brown, Damon Payne, Agata Staniak, Justin Angel, and David Anson. Shoutout: John

Tuesday, December 30, 2008 12:45 PM by Community Blogs