DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report

Reusing Your Existing Silverlight Components With Windows Phone 7

Gergely Orosz user avatar by
Gergely Orosz
·
Mar. 17, 11 · Interview
Like (0)
Save
Tweet
Share
10.98K Views

Join the DZone community and get the full member experience.

Join For Free
Using .NET is all about leveraging your code across platforms. That was true with previous versions of Windows Mobile OS and it's true in today's XAML-centric environment. But with Silverlight, a .NET developer must pay special attention to the separation of core logic and UI in order to reuse the most code. By organizing your app into the MVVM, or Model-View-Presenter (aka View-Model) pattern, you'll be able to reuse a surprising amount of code between your Web-based Silverlight apps and your Windows Phone 7 apps. This walkthrough will take a basic Silverlight app and demonstrate how to do just that.

This tutorial is structured of the article as follows:

  • MVVM and Reusing of Code
    • MVVM Overview
    • Resusing the Code with MVVM
  • Reusing Silverlight Components With WP7: An Example
    • The Silverlight Application
    • Porting the Silverlight Application to Windows Phone
    • Download the Code
  • Further Thoughts on Code Reuse Between Silverlight and Windows Phone
  • Summary


MVVM and Reusing of Code

MVVM Overview

MVVM is an architecture pattern that aims to organize code in three layers: the Model, the View and the ViewModel. There are numerous advantages of doing so, the most important ones being:
  • Separation of GUI logic and application logic. The pattern completely separates the View and the Model, so when changes are made in either, they can be done leaving the other unaffected.
  • Support for unit tests. The application's functionality can fully tested by writing unit tests, minimizing (or removing) the need of UI-based tests.
  • Tool support. The View populated by mock data can be edited in Blend and Visual Studio by designers without modifying other parts of the project.
Another advantage of MVVM - that is often overlooked - is that it enables efficient reusing of the code when porting between Silverlight, Windows Phone 7 (and to some extent, WPF as well).


Reusing The Code With MVVM

MVVM makes code reuse particularly powerful between Silverlight and WP7 applications thanks to the structuring of its layers. The Model contains the business logic without framework specific details, thus all of it can be shared between the Silverlight and WP7 implementations. If the application's UI logic is identical or similar for both applications, most of (if not all) of the ViewModel layer code can be shared as well. The View, however in most cases is significantly different for the Silverlight and WP7 applications. Even though it is possible to share parts of the View between the two projects, since a web UI is usually very different from a phone UI, doing so usually doesn’t make sense.

By using MVVM it is thus possible to reuse all of the code of the existing Silverlight application apart from the View. Considering Silverlight web applications and Windows Phone 7 ones call for different user interfaces most of the time, this means that with MVVM one only has to rewrite the UI specific part of the application.


Reusing Silverlight Components With WP7: An Example

To understand how code can efficiently be reused from an existing Silverlight application when porting to Windows Phone 7, let's walk through a simple example - a savings calculator.


The Silverlight Application

The Silverlight application in this example is a simple savings calculator which looks like this when running:



In the application the user has to enter the initial deposited amount, monthly deposit, annual interest rate and number of years to save for. The application then calculates the total deposited amount as well as the final savings with the annually compounded interest added.

In the application the three layers of the project are structured in three separate projects. The model is a Silverlight 3 class library named SavingsCalculatorModel, the ViewModel is also a SL 3 class library named SavingsCalculatorViewModel and the View (the application to be run) is a SL 4 application named SavindsCalculatorSilverlight. Dependencies are the same one way as in the MVVM pattern: the ViewModel project references the Model and the View project references the ViewModel.

Having outlined the UI and architecture of the example application, let's take a look at how it's implemented using Silverlight.


The Model

The model layer is responsible for implementing the business logic. In the case of this savings calculator application this means the responsibility of calculating the savings without and with interest. The code of the model is quite simple, consisting of several properties and the CalculateSavings method which calculates the total deposit and the final savings. The code for this is as follows:

public class SavingsCalculatorModel
{
public int NumberOfYears { get; set; }

public double AnnualInterest { get; set; }

public double InitialAmount { get; set; }

public double MonthlyDeposit { get; set; }

public double FinalSavingsWithInterest { get; private set; }

public double FinalSavingsWithoutInterest { get; private set; }

/// Calculates FinalSavingsWithInterest and FinalSavingsWithoutInterest based on
/// InitialAmount, NumberOfYears, AnnualInterest and MonthlyDeposit
public void CalculateSavings()
{
// See source for details
}
}

The View

In the View we display input fields for all of the required details, a button to initiate calculation and the outcomes of this calculation. To do so we'll need to create TextBlock elements for the texts, TextBoxes for the input and a Button for the calculation button.

The values of the input TextBoxes are data binded to members of the ViewModel. This is done via a two way binding so that changes made by the user are applied on the ViewModel. For example the input field for the annual interest is set up the following way:
<TextBox Text="{Binding InitialAmount, Mode=TwoWay}"/>
We also need to bind the result of the calculations to the view. The results are not to be changed by the user, thus we can use a one way binding (and since this is the default, there's no need to specify the binding mode).
<TextBlock Text="{Binding FinalSavingsWithInterest}" FontWeight="Bold"/>
The final part of setting up the View is forwarding the Click event of the Button to the ViewModel. This is done by commanding - that is relaying commands to the ViewModel. To do so, we need to bind the Command property of the Button to an ICommand to be exposed on the ViewModel:
<Button Command="{Binding CalculateCommand}"/>
The code for the View can be found in the attached source code in the MainPage.xaml file.

public class SavingsCalculatorViewModel: INotifyPropertyChanged
{
private SavingsCalculatorModel _model;

public int NumberOfYears
{
get
{
return _model.NumberOfYears;
}
set
{
_model.NumberOfYears = value;
}
}
// Similarly wrapping of AnnualInterest, InitialAmount, MonthlyDeposit, FinalSavingsWithInterest and FinalSavingsWithoutInterest
(...)

public ICommand CalculateCommand
{
get
{
return new RelayCommand(CalculateSavings) { IsEnabled = true };
}
}

private void CalculateSavings()
{
_model.CalculateSavings();
RaisePropertyChanged("FinalSavingsWithoutInterest");
RaisePropertyChanged("FinalSavingsWithInterest");
}

// Constructor initializing the default values and INotifyProperyChanged implementations
(...)

The ViewModel

The ViewModel is responsible for gluing the Model and View together. It will have to expose all the properties that the View will bind to and wrap these around the Model. In this example the ViewModel is pretty simple: it acts as wrapper around the model, sets default values on it when initializing and exposes the CalculateCommand command to be triggered when the calculate button is pressed. In the example a simple ICommand implementation is used - Josh Smith's RelayCommand version. The important parts of the ViewModel code are the following:

public class SavingsCalculatorViewModel: INotifyPropertyChanged
{
private SavingsCalculatorModel _model;

public int NumberOfYears
{
get
{
return _model.NumberOfYears;
}
set
{
_model.NumberOfYears = value;
}
}
// Similarly wrapping of AnnualInterest, InitialAmount, MonthlyDeposit, FinalSavingsWithInterest and FinalSavingsWithoutInterest
(...)

public ICommand CalculateCommand
{
get
{
return new RelayCommand(CalculateSavings) { IsEnabled = true };
}
}

private void CalculateSavings()
{
_model.CalculateSavings();
RaisePropertyChanged("FinalSavingsWithoutInterest");
RaisePropertyChanged("FinalSavingsWithInterest");
}

// Constructor initializing the default values and INotifyProperyChanged implementations
(...)

Porting the Silverlight Application to Windows Phone

Now that we've seen how the Silverlight application is constructed, let's look into porting it to Windows Phone 7. We want to maintain the same application logic, but optimize the UI a bit better for the phone to give it a native feel. The ported Windows Phone 7 application will look as follows after we've finished:



Porting of the Model and ViewModel

Since the business logic hasn't changed, all the code of the model is reused in the WP7 application. In this example, the Model was a Silverlight class library, thus the Windows Phone project simply needs a reference pointing to the model project.

Our UI requirements are functionally the same as for the Silverlight application, meaning that all of the ViewModel code can also be reused as well - no coding needed so far!


Porting the View

When porting the view of the application there's not much point in reusing the View of the Silverlight application. On the interface of the phone we'd want a UI that blends in to the WP7 world. We'll need to modify the original View to achieve this. Some of the changes that we're making in the view are as follow:

  • We want the form to fill most of the phone screen and offer input boxes large enough to be easy to tap. To do so, instead of using the default text style we'll use larger fonts by using the built-in Windows Phone theme resources:
    <TextBlock Text="Monthly Deposit:" Style="{StaticResource PhoneTextTitle2Style}" />
  • By default when tapping a text input field the user is presented with a keyboard with alphabetical letters on it, forcing the user to switch to numerical ones to enter numbers. To avoid this, let's set the InputScope property on the TextBoxes to Number:
    <TextBox Text="{Binding InitialAmount, Mode=TwoWay}" InputScope="Number"/>
  • Bold text doesn't stand out as much on the phone than it does on the web. To have the final savings value stand out more, let's set its color to be the phone's accent color:
    <TextBlock Text="Final Savings:" Foreground="{StaticResource PhoneAccentBrush}" Style="{StaticResource PhoneTextTitle2Style}" FontWeight="Bold" />
  • Windows Phone doesn't have support for ICommands on input elements, thus we'll have to tap into event triggers and have these triggers forwarded to commands. We'll be using the EventToCommand helper class from MVVM Light to do so. See the Implementing Commanding in a Consistent Way section for more details on this.



Porting Overview

Porting this Silverlight application to Windows Phone proved to be surprisingly easy: we were able to reuse the Model and ViewModel layers of the original application without modification and only had to rewrite the View. However, since a Silverlight application to be run in a browser and that on a phone require different user interfaces, we would have had to make changes to the phone UI in all cases.

Overall it's safe to say that by having developed the Silverlight example following the MVVM pattern, we were able to port it to Windows Phone 7 by reusing most of its code and only rewriting the Windows Phone user interface specific part - the View.



Download the Code

The solution containing the Model, ViewModel, the Silverlight View and the Windows Phone 7 View can be downloaded from here. To run the Silverlight application, build and run the SavingsCalculatorSilverlight project, for the Windows Phone application build and run the SavingsCalculatorWP7 project.


Further Thoughts on Code Reuse between Silverlight and Windows Phone

Reusing Parts of the View With UserControls

In the example we didn't reuse any part of the View. The main reason for this was that the XAML of a Silverlight page and that of a Windows Phone page is different, making the sharing of the same XAML not possible.

However, it is possible to reuse UserControls between Silverlight and Windows Phone applications. This can be done both at assembly level or by referencing the XAML of the UserControl.


Possible Problems When Reusing Silverlight Components with Windows Phone

Structuring the Silverlight project following the MVVM pattern does not always guarantee that the code will be 100% reusable. If the Silverlight application uses APIs that are not implemented on the Windows Phone 7 Silverlight runtime, the project will not compile for Windows Phone. As Windows Phone 7 runs an extended Silverlight 3 runtime, at the moment this issue is mostly localized to the few new APIs introduced by Silverlight 4. However, when Silverlight 5 for the web is released, this issue will probably be a more important one.

There are a few workarounds to resolve this, the two most common ones being:

  • Wrap the Silverlight 4 (or later on, Silverlight 5) specific calls between #if !WINDOWS_PHONE (...) #endif macro definitions. This way they will only be compiled in the Silverlight project as the default Windows Phone project has the WINDOWS_PHONE constant defined.
  • Use partial classes and move the framework version-specific logic into a partial class file only referenced by the Silverlight solution.



Implementing Commanding in a Consistent Way

In the example we've implemented commanding (binding the command of the button to an action in the ViewModel) different for the Silverlight application than for the Windows Phone port. The reason for this was that Windows Phone input controls only have notions of triggers, not commands. We've solved the situation by using the MVVM Light framework's EventToCommand helper class to forward the events invoked by triggers to the commands on the ViewModel. This means that while inside the Silverlight project we've used the following syntax to bind to a command:
<Button Content="Calculate" Command="{Binding CalculateCommand}" />
In Windows Phone on the other hand, we used this syntax:
<Button Content="Calculate" xmlns:mvvmlight="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7" xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="Click">
<mvvmlight:EventToCommand Command="{Binding CalculateCommand}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</Button>
This situation could have been avoided by using the same MVVM framework for both the Silverlight and WP7 project. In the example simplicity was the key, thus no MVVM framework was used in the Silverlight example. However in a real-world project it's definitely worth using the same framework across the Silverlight and Windows Phone 7 projects to maximize the code reuse. MVVM frameworks supporting both Silverlight and WP7 environments include MVVM Light, Caliburn Micro and - to certain extent - Prism (Silverlight and WP7 build).


Summary

The article has briefly highlighted some key advantages of using MVVM in Silverlight projects and has outlined how structuring a project following the MVVM pattern helps code reuse when porting to Windows Phone. It then gave a walkthrough creating a simple example - a savings calculator - giving a quick overview of how the project is structured. It then explained how to port it to Windows Phone, reusing all of the code except for the UI specific View layer. Finally, it explored some other topics that might be important when reusing Silverlight code on WP7, such as reusing parts of the view, commanding and possible problems.

Summing it up, the article has shown yet another advantage of structuring Silverlight projects following the MVVM pattern. By doing so it's possible to later port it to Windows Phone 7 only having to rewrite the user interface specific parts of the application.
Windows Phone mobile app

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • What Is API-First?
  • Choosing the Right Framework for Your Project
  • What “The Rings of Power” Taught Me About a Career in Tech
  • Documentation 101: How to Properly Document Your Cloud Infrastructure Project

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: