In-Depth

Porting a Silverlight App to a Metro-Style App

Many developers are worried about the compatibility of Silverlight with Metro-style applications. This project shows that those fears are overblown.

Windows 8, which was introduced at the Microsoft BUILD conference last year, is an exciting new OS that introduced a new UI as well as a new runtime: Windows Runtime, called WinRT. It's the backbone of the new Metro experience in Windows 8. Like many others, I've been playing with Windows 8 and kept hearing that Silverlight skills can be reused in Metro-style applications. I decided to find out for myself by taking a Silverlight 2 project and seeing how easy it was to port to a Windows 8 Metro application using C#/XAML.

Enter Silverlight 2
Several years ago, Scott Guthrie, corporate vice president of Microsoft Server & Tools Business, posted a seven-part series he called "First Look at Silverlight 2". The series walked readers through building a Silverlight 2 application. Some of the important concepts taught in the series included:

  • Layout Management
  • Networking
  • ListBox and DataBinding
  • User Controls
  • Control Templates

At the end of the series, the completed project looked like Figure 1.


[Click on image for larger view.]
Figure 1. The Silverlight 2 Digg Client in its completed form.

If the user clicked on an item, Figure 2 was the result.


[Click on image for larger view.]
Figure 2. The Silverlight 2 Digg Client after a user clicked on an item.

Finally, clicking on the title would launch the default browser with the current story.

I was interested in seeing just how easy it would be to do a direct port of this code over to a Metro application. Note that I'm not trying to make this application fit the Metro guidelines in Windows 8. I simply want to run this as a Metro application in Windows 8 using C#/XAML.

The Initial Assessment
The first step was to download a completed version of Guthrie's Digg client sample, available here, and uncompress it to a temp folder. I then navigated to the \DiggSample_CSharp\DiggSample folder and inspected the files shown in Figure 3.


[Click on image for larger view.]
Figure 3. The DiggSample Silverlight 2 project uncompressed to a file folder.

After looking through the file structure, I decided I'd need only the following files:

  • App.xaml. Application Initialization, which contains all of the Styles the application is using. (Note: App.xaml.cs wasn't needed, as it didn't contain any custom code.)
  • DiggStory.cs. Contains a class called DiggStory with each element that will be used later in the LINQ statement.
  • Page.xaml/Page.xaml.cs. The UI shown in Figure 1 with code that will definitely have to change because it uses WebClient.
  • StoryDetailsView.xaml/StoryDetailsView.xaml.cs. The UI shown after a user selects an item. The codebehind looks simple and won't have to change.

Download and Installation
Using the Windows 8 Developer Preview, I launched Visual Studio 11 and selected Windows Metro style/Application and named it DiggSample (just like the original project), as shown in Figure 4.


[Click on image for larger view.]
Figure 4. A new Windows Metro-style project in Visual Studio 11.

I decided to start with the DiggStory.cs file first because it was a simple class that wouldn't need any modification. Listing 1 shows the class.

Because my project is also named DiggSample, all I had to do was copy and paste the class into my project. Right off the bat I thought I'd have to fix my namespaces. Here are the default Metro application XML namespaces:

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
x:Class="DiggSample.App" />

And the DiggStory Silverlight application XML namespaces:

<Application xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
x:Class="DiggSample.App">

The only difference is the first XML namespace. Because I'm creating a Metro application, I was able to leave the Metro application XML namespace untouched. The only thing I needed to do was copy <Application.Resources> out of the Silverlight application and into my Metro application.

I hit "build" and received the error shown in Figure 5.


[Click on image for larger view.]
Figure 5. The Error List window detailing an unknown type in RadialGradientBrush.

After searching the Web, I found that RadialGradientBrush isn't included in the current build (the reasoning pertains to GPU acceleration, as explained in the MSDN Forums). Nor is it supported in the Microsoft .NET Framework 4.5.

Instead of the RadialGradientBrush, I decided to use the LinearGradientBrush for this sample.

I replaced this code:

<RadialGradientBrush GradientOrigin=".3, .3">
  <GradientStop Color="#FFF" Offset=".15"/>
  <GradientStop Color="#777" Offset="1"/>
</RadialGradientBrush>

With this:

<LinearGradientBrush>
  <GradientStop Color="#FFF" Offset=".15"/>
  <GradientStop Color="#777" Offset="1"/>
</LinearGradientBrush>

This resulted in a successful build.

Next, I added a new User Control called StoryDetailsView. I then opened the existing StoryDetailsView.xaml from the DiggStory solution and noticed the XML namespace was identical to the default Metro application. So I copied and pasted the entire StoryDetailsView.xaml inside my Metro application and hit "build" again. I was immediately greeted with the error shown in Figure 6.


[Click on image for larger view.]
Figure 6. The Error List window detailing several unknown members.

There's an error stating that the NavigateUri doesn't exist on HyperlinkButton. It existed in Silverlight and Windows Phone, so where is it in WinRT?

This is where I discovered the differences in the XML namespaces being used. Hovering on top of the HyperlinkButton brings up the text shown in Figure 7.


[Click on image for larger view.]
Figure 7. The Windows.UI.Xaml.Controls.HyperlinkButton in Windows Runtime.

This demonstrates that a Metro-based Hyperlink class inherits the ButtonBase class without any special properties or events, such as NavigateUri. I can quickly fix this by removing NavigateUri and adding a Click Event Handler that will navigate to the Web site in the default browser. Here's how to fix it:

<HyperlinkButton x:Name="hlbStoryTitle" Content="{Binding Title}"  
  Click="HyperlinkButton_Click" Style="{StaticResource TitleLink}" 
  Tag="{Binding HrefLink}" />

Notice the Tag on the HyperlinkButton to pass the current URL. If I add the event handler and build the project again, it will compile successfully.

Next, I needed to add in our event handler for the HyperlinkButton and copy/paste the existing Close Button event handler:

void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
  Windows.System.Launcher.LaunchDefaultProgram(
    new Uri(hlbStoryTitle.Tag.ToString(), UriKind.RelativeOrAbsolute));
}
void CloseBtn_Click(object sender, RoutedEventArgs e)
{
  Visibility = Visibility.Collapsed;
}

By using Windows.System.Launcher.LaunchDefaultProgram, I was able to pass it a URI so it automatically launches the default browser. This method can only be called from a click event or some other user interaction.

In Silverlight 2, the MainPage was just called Page.xaml. This changed in Silverlight 3 with the name MainPage.xaml (which is also what Metro applications use).

With that out of the way, let's look at the XML namespaces again.

The Page.xaml inside the Silverlight application looks like this:

<UserControl x:Class="DiggSample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:Digg="clr-namespace:DiggSample">

I was able to copy and paste the entire Page.xaml inside of my MainPage.xaml file and fix the following namespaces for the Metro application:

<UserControl x:Class="DiggSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:Digg="using:DiggSample">

Notice that DiggSample.Page turned into DiggSample.MainPage (remember what I said earlier about Silverlight 2?), and instead of using "clr-namespace" I used the "using" statement in WinRT applications.

If I run the application, it won't compile because I don't have event handlers set up for the buttons. That's OK for the meantime.

Here are the existing methods in MainPage.xaml.cs:

  • searchBtn_Click. I know I'll need to see if the Digg API has changed and that I can't use WebClient in Metro applications.
  • DiggService_DownloadStoriesCompleted. Will more than likely be removed because it's part of the WebClient.
  • DisplayStories. Can be reused as long as the Digg API didn't change.
  • StoriesList_SelectionChanged. Can be reused completely.

Initial Assessment of the Digg API
One thing I had to research was the Digg API. I assumed (correctly) that it had changed since 2008. But what had changed?

In Scott Guthrie's example, it calls the following URL:

 http://services.digg.com/stories/topic/{0}?count=20&appkey=http://www.scottgu.com

Here, {0} is the name of the search term.

I tried that URL and found out it returns nothing. After reading the Digg API -- which is deprecated again -- I found that it's changed to the following:

http://services.digg.com/search/stories?query={0}&appkey=http://www.scottgu.com 

Again, {0} is the name of the search term.

So I replaced the URL with the new one, leaving the appkey as is. (Request your own appkey if you're planning on using the digg API in your own applications.)

The next review item was the XML returned by the service, to see how well it matched the DisplayStories method. Listing 2 is sample XML returned by the Digg API using the service mentioned earlier.

I took each item from the DiggStory class, made sure it still existed and that the data type was correct. The only item that concerned me was the ID, as Guthrie's sample code cast ID as an integer. From looking at some random sample data it appears the ID is no longer an integer. I did several Google searches and others had hit this issue and recommended using a string, which I did.

The Search Button Event Handler
The existing search button event handler looked like Listing 3 in Silverlight.

I changed it to what's shown in Listing 4.

The only differences are marking the method as async, and instead of using WebClient I used HttpClient, and for the response I used HttpResponseMessage. I then passed the responseString into the existing DisplayStories that Guthrie had built. The DiggService_DownloadStoriesCompleted method was no longer needed, so it was removed.

DisplayStories Method
Because I knew I'd have problems with ID, I simply changed it from an integer to a string, as shown in Listing 5.

This caused a ripple effect and broke DiggStory.cs, so I changed ID to a string here as well. The result is shown in Listing 6.

I was all set, so I built the solution and everything compiled successfully.

Then the moment of truth: Run it!

After running the application, it appeared just like it did with the Silverlight application. Figure 8 shows the UI, waiting for input.


[Click on image for larger view.]
Figure 8. The Windows Simulator running the Metro version of the Digg Client Sample, waiting for user input.

I typed "Microsoft" into the search box and noticed I had the clear text option as well.

I then hit "Search"; the results are shown in Figure 9.


[Click on image for larger view.]
Figure 9. Data being returned to the Digg Sample Metro application.

I then selected an item and got the window shown in Figure 10.


[Click on image for larger view.]
Figure 10. A selected item in the Digg Sample Metro application.

Clicking on an item title will launch the story in Internet Explorer.

I then took Guthrie's existing Silverlight 2 application and updated the Digg API; it immediately worked in the Windows 8 Desktop Mode.

The Best of Both Worlds
Every Microsoft-focused developer should be learning about Metro applications. It's also important that Silverlight developers begin to understand how to work with this new technology using their existing skillset.

What did I learn from this exercise?

  • XAML is XAML. If you can write XAML in Silverlight, you can easily port that code to Metro applications.
  • It's safe to write a Silverlight application today and port it over four years from now when Metro becomes more mainstream.
  • The crucial factors are the differences in XML namespaces and the asynchronous nature of Metro applications.

Silverlight developers have the best of both worlds. They can create an application in native Silverlight and easily port it to Metro, or run it on the Windows 8 Desktop. HTML5 developers don't get this luxury.

comments powered by Disqus

Reader Comments:

Fri, Feb 15, 2013 Gerrilyn viagra :-((( infinity auto insurance 6796 cipro >:(

http://www.medsadvisor.net/ DOT :-((( http://www.cheapcarinsuronline.com/ DOT 6796 http://www.treatmentforinfections.com/ DOT >:(

Sun, Jul 22, 2012

Don't forget Microsoft are offically supporting Silverlight for the next 10 years. Silverlight will run on older versions of windows. Metro is windows 8 only. Silverlight is designed for mouse and keyboard, metro designed mainly for touch. Even the knuckle-heads at MS thought that Silverlight's sweet-spot was LOB apps.

Wed, Jul 18, 2012

The worst part of it is that you can't even share code between platforms - WPF, Silverlight, Metro - because the development team under Sinofsky couldn't be bothered with compatibility. The XAML namespace declarations in Metro are different from WPF/SL and this makes it impossible to link and share code between both architectures. Heavy handed and inconsiderate, dev team!

Fri, Jun 1, 2012 Lars Redmond

Silverlight is the best thing Microsoft has accomplished in the last decade. The best that can happen is that the world rejects the HTML5 or flimsy XAML Metro solutions and Microsoft wakes up to at the very least provide a version of Silverlight which runs on the ARM tablets and within the Metro system.

Wed, Mar 28, 2012 Jules

We have spent three years developing a deep LOB app with Silverlight. And no we find that Microsoft dumped us in the sh*t. This is a trvial Application, we have got 10,000 + lines of XAML and Silverlight code and Controls ! How can we have confidence that Metro will be portable across the Web ? - Javascript HTML5 simply does not deliver in LOB Applications , so where do we go now ?

Wed, Mar 14, 2012 Thomas

What is better in Metro than in Silverlight? Silverlight at least has the approach to run on multiple platforms, can run in the browser as well as oob. WinRT is a step back, runs only on Windows. Modern Apps MUST run on different boxes. MS schould invest into Silverlight and Platforms, not in reinventing the wheel.

Wed, Mar 14, 2012

As to one of the questions asked earlier, Metro applications are exclusive to Windows 8, built upon a framework that's nowhere as worthwhile as that provided by Silverlight, and where they'll most likely become just as irrelevant as applications once built to exploit features of Visita. Oh, and Bob, he needs a big-time clue - we may need stage an intervention once he realizes all that's really NOT going on in Redmond....

Wed, Mar 14, 2012 Bob

Guys, get real- nobody ever said metro was for LOB apps - instead they said metro is for CONSUMERS. Now: whether you support it or not - millions of Web/JavaScript Developers are not equal in developing also solutions for Windows 8 - yes its a new world and yes it requires re-thinking but there is many opportunities out there for consumer solutions - which is what metro is for

Wed, Mar 14, 2012

So I spend time and effort developing a Silverlight application only to find out it is obsolete, can only run in a Metro desktop, and will probably have limited support in future OS versions (like was done with DOS). So now I should spend time and non-trivial effort converting my Silverlight application to Metro so it is not a second class application? How do I know Metro will not go down the tubes like Silverlight? Is a runtime provided so that Metro applications run on older versions of Windows? Or will only Windows 8 users be able to run Metro applications?

Tue, Mar 13, 2012

Gah - that's a toy application. Metro doesn't support 50% or more of the controls needed by a Line of Business app. It's a non-starter for porting a real application - the lack of a data grid alone kills it. We're going to have to port to something else entirely.

Tue, Mar 13, 2012

A more worthwhile article would focus on the opposite - how the best of the best of us will port a bunch of Metro apps to Silverlight after the epic-fail of Windows 8 (dwarfing that of Vista) makes such apps entirely irrelevant...

Tue, Mar 6, 2012 Ian Walker The Malverns

Great job, hopefully my own Silverlight ports will be this easy (plan on starting soon)

Mon, Mar 5, 2012 mike

Metro is a huge FAIL. Dont even wast your time.

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.