Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Porting iPhone Apps to Windows Phone 7
1. Porting an iPhone Application to Windows Phone 7
Introduction
Developers of iPhone applications possess the fundamentals and key understanding for building
applications for small form factor devices. When creating a mobile application for Windows Phone 7
however, the means for developing the application changes. This platform is a considerable departure
from Microsoft’s previous mobile operating systems so this article will help describe what you’ll
encounter porting an existing iPhone application to Windows Phone 7.
Whether it’s the difference between Objective-C vs .Net, or the iOS SDK vs the Windows Phone 7 SDK, a
number of differences exist which will be explained throughout this article. We’re going to walk through
our own process of porting an internal iPhone application, Slalom Cards, into a comparable version for
Windows Phone 7. The goal of this article is not only provide you with the knowledge necessary to port
an existing application to Windows Phone 7, but to also better understand the platform a whole for new
development.
About the Team
Rob Howard is an experienced software engineer and engineering lead. He has ten
years of industry experience with published mobile applications for several
platforms including iPhone, WebOS, and Blackberry. He has a career in both
Consulting and Startups, building software from the ground up and taking a project
to the latest technologies or methodologies. Rob strives to make solutions simple,
understandable, and easily extendable.
Dan Maycock is a technology solutions consultant, helping advise fortune 500
companies on how to work with new and emerging technologies, primarily focused
around mobile. Prior to working for Slalom Consulting, Dan worked at The Boeing
Company, where he helped shape the direction for enterprise mobility and
successfully pioneered a number of initiatives focused around successfully utilizing
mobile technologies to help solve business challenges.
Greg Martin has been a consultant at Slalom Consulting for over 7 years and is
currently the mobility development lead. Greg is a talented software engineer and
consultant with experience in a wide variety of technologies and industries.
He has spent much of his career delivering solutions in the mobile space. Beyond
his deep technical knowledge, Greg also excels in the entire lifecycle of a project
with an uncanny ability to break a problem down into the most elegant solution.
Slalom Consulting
Slalom Consulting is a business and technology consulting firm that helps clients win by building local
teams with a deep understanding of the art and science of business success. Slalom drives client ROI in
2. areas such as cloud computing, business intelligence, portals, mobility, project management and process
design. Slalom's consultants are handpicked experts who stay ahead of the curve by always finding the
next innovative advantage. Headquartered in Seattle, Slalom employs more than 800 consultants across
eight cities in the United States.
Slalom Cards
The application listed in this article was built to serve as a dynamic corporate directory, complete with
profile photos, background information and a feature set focused on finding people based on many
characteristics. Originally built for the iPhone, it has since been ported to Android and Windows Phone
7, as well as being extended to a web-based platform.
Getting Ready
Resources
Windows Phone 7 applications are built and tested utilizing Visual Studio. All the tools to get started can
be downloaded at http://developer.windowsphone.com/windows-phone-7/ as well as guides and tips
to get up to speed with the Windows Phone 7 development environment.
As a (fairly obvious) note, the development environment DOES require the Windows Operating System
(Windows Vista or Windows 7), so having either a standalone machine, or a VM with the OS will be
required before you can utilize the Windows Phone 7 development toolset.
You will need to download the developer tools on this website. They are a free download and it
includes the following:
a. Visual Studio 2010 Express for Windows Phone Beta
b. Windows Phone Emulator Beta
c. Silverlight for Windows Phone Beta
d. Microsoft Expression Blend for Windows Phone Beta
e. XNA Game Studio 4.0 Beta
f. The UI Design and Interaction Guide for Windows Phone 7 can be found linked on the
Windows Phone developer site at http://go.microsoft.com/?linkid=9713252
Documentation
Since we are jumping from one platform to another, it’s important to map out the ins and outs of your
existing application. This might include everything from doing a high-level outline, to writing pseudo-
code as a reverse engineering exercise. Regardless, knowing how the application is laid out will help
further down the road once you get deep into the code.
Construction of the Application
The Easy things
3. Migration of the Data Model
Since the languages support similar features (both object-oriented c-like languages that support things
like properties and methods) porting most of the model items will be pretty straightforward with a one
to one mapping of fields and methods. Note: C# is currently the only supported programming language
for Development for Windows Phone 7.
Networking
Windows Phone 7 allows the developer to use Windows Communication Foundation (WCF),
HttpWebRequest, and WebClient.
WCF works very well with SOAP web services. It is very simple to set up a connection that would
generate all of the networking code and object classes that it uses.
For RESTful services, WCF is also very useful but we will have to do a little bit more work deserializing
the data into objects. There are many ways to do this; .Net provides some simple DataContract
Serializers and Deserializers that work well with XML and JSON.
User Interface Elements
Windows Phone 7 provides a few ways to author and edit the user interface.
One can use the preview pane within the IDE for layout and addition to controls. This is very similar to
the Interface Builder application that is part of the iOS SDK. Users of Interface Builder will become easily
familiar with this method of UI authoring and manipulation.
Also in the IDE is a view of the XAML that can be very useful for a developer to see and modify. This
code behind the presentation is an easy way to see the output of the UI layout engine, and gives a
chance to add function handlers, custom properties on classes, and to fine tune your code.
There is also a version of Expression Studio for the Windows Phone. Like Expression for web based
Silverlight applications or WPF implementations, this provides a more designer focused interface which
allows you to creating templates, behaviors, animations, and many other custom UI.
Page Hierarchy
Like most mobile phone operating systems, Windows Phone 7 provides a stack based navigation system
along with application buttons that can be used, like in the iPhone, as a tabbed based navigation system.
The API provides NavigatedTo and NavigatedFrom methods that are similar to the ViewDidAppear, and
ViewDidDisappear methods that the iPhone supports.
The Difficult and / or Not so clear things
4. This is a list of things that aren’t as simple as the first list. Differences in hardware, operating systems,
and API are the contributing factor to getting an item in this list.
Data storage
Unlike previous versions of Windows Mobile operating systems, Windows Phone 7 currently does not
have an API for a client-side database which developers can use.
What is provided is access to isolated data storage where your application can save settings or files.
Here you can roll your own data storage mechanism or use a third party database with the caveat that
an application can only access its own data. This is very similar to those familiar with iPhone
development and is another break away from previous versions of Windows Mobile operating systems.
A resource video for developing occasionally connected applications can be found here:
http://www.msteched.com/2010/NorthAmerica/WPH306
Page Transitions
While the navigation between pages in the Windows Phone 7 environment is similar to iPhone, the
familiar animation transitions are not left up to the developer to implement.
Built-in screen transitions and animations are system-reserved and developers cannot access them but
may mimic them. If developers want to implement transitions or animations within their application,
they must use Silverlight or the XNA Framework to create them (see page 64 of the UI Design guide).
Transitions within your application must be implemented on your own.
Contrary to the iPhone, there currently isn’t a defined standard for the types of transitions one should
use.
A Channel9 video of implementation can be seen here:
http://channel9.msdn.com/posts/SlickThought/Simplify-Page-Transitions-in-Windows-Phone-7-
Silverlight-Applications/
Windows Phone 7 Has Themes
There is a large selection of highlight colors including light and dark for background colors.
One must be aware that the user could have any one of those themes set for their phone. The
application should be aware of the settings and use them throughout the user experience.
Background images and UI elements presented above them should take in to account the possibility of
the different themes. For example, if you use a particularly dark image for a background, the light
theme with black button borders may not show up very well against the image. Setting the opacity of
5. the image to show some of the white background is one solution to this problem.
Digging Deeper
The following are some examples that we used in Slalom Cards. We chose these examples because we
felt that they are things that aren’t obvious to most developers and take some research to find a
solution. We also feel that they are things that pretty much any application for the phone would need.
Some are simplified versions of examples that others have created or ones that we fixed due to the SDK
changes in the Windows Phone 7 in its push to production. In our samples, we try to find a simple
solution to the problems while providing the best user experience.
Porting the Data Model – The following is simple port of a small class from Objective-C to C#. This
would be part of a class that would represent the data behind user interface elements. It could be
created in several different ways, like being fetched from storage, from an external API, or being
generated by the application at runtime. In the example, the extra methods for those means of creation
or fetching have been omitted to keep the code short:
Person.h
@interface Person : NSObject
{
}
@property (nonatomic, retain) NSString * firstName;
@property (nonatomic, retain) NSString * lastName;
@property (nonatomic, retain) NSString * office;
Person.m
#import "Person.h"
@implementation Person
@synthesize firstName;
@synthesize lastName;
@synthesize office;
-(void)dealloc
{
[firstName release];
[lastName release];
[office release];
[super dealloc];
}
@end
Person.cs
public class Person
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Office { get; set; }
}
6. C# also provides an easy way to port Observable objects. The following code is an
update of the Person class to notify observers of updates to the data.
public class Person : INotifyPropertyChanged
{
private String firstName;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChanged(String changeProperty)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(changeProperty));
}
}
public String FirstName
{
get
{
return firstName;
}
set
{
if (value != firstName)
{
firstName = value;
NotifyChanged("FirstName");
}
}
}
…
Navigation – Moving from page to page in your application is different than iPhone, but fairly simple.
Instead of pushing and popping view controllers to your scene, the navigation system behaves more like
a browser where you navigate forward and back through the pages of the application. Also, data is
passed to the pages through the querystring where the navigating page can read and perform
operations based on the input. This is shown in the following examples:
A typical navigation operation in iPhone
PersonListViewController * personList = [[PersonListViewController alloc]
initWithNibName:@"PersonList" bundle:nil];
[[self navigationController] pushViewController: personList animated:YES];
[personList release];
Doing the same in code on Windows Phone 7
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/PersonListPage.xaml?office=Seattle",
UriKind.Relative));
}
A different way, with XAML
<HyperlinkButton Content="Seattle" NavigateUri="/PersonListPage.xaml?office=Seattle" />
<HyperlinkButton Content="Los Angeles" NavigateUri="/PersonListPage.xaml?office=Los Angeles" />
Reading passed in values on the new page
7. protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
PersonList people = CardsDatabase.Instance.PersonListTable;
string office;
if (NavigationContext.QueryString.TryGetValue("office", out office) == false)
{
office = "National"; // default value
}
PersonList.ItemsSource =
from p in people
where p.Office == office // filter to the selected office
orderby p.FirstName, p.LastName
select p;
}
Navigating back to the previous page is either done with the user clicking on the
back hardware button or you can programmatically perform this with the following
code:
NavigationService.GoBack();
Page Transitions – As stated earlier, the Windows Phone 7 SDK leaves it up to the developer to create
animations and transitions while navigating between pages. A simple way to add these transitions to
your application is to use the TransitioningContentControl in the Microsoft Silverlight Toolkit found at
http://silverlight.codeplex.com/. The steps to add these transitions are as follows:
1. Download and install the toolkit.
2. Add a reference in your project to
System.Windows.Controls.Layout.Toolkit.dll (for example after installation,
it was found in: Program Files (x86)Microsoft
SDKsSilverlightv4.0ToolkitApr10BinSystem.Windows.Controls.Layout.Toolk
it.dll)
3. In your App.xaml file, create a Style for the application frame that
includes a TransitioningContentControl
<Application
x:Class="Cards.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:tcc ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
>
<Application.Resources>
<Style x:Key="mainFrameStyle"
TargetType="phone:PhoneApplicationFrame">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="ClientArea"
BorderBrush="{TemplateBinding
BorderBrush}"
BorderThickness="{TemplateBinding
BorderThickness}"
8. Background="{TemplateBinding
Background}"
HorizontalAlignment="{TemplateBinding
HorizontalAlignment}"
VerticalAlignment="{TemplateBinding
VerticalAlignment}">
<tcc:TransitioningContentControl
x:Name="TransitioningControl" Content="{TemplateBinding Content}" Style="{StaticResource
TransitioningStyle}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Also in this file, create the transition templates for the page transitions. For
the example, a SwingOpen transition for navigating forward and a SwingClosed
transition for backward navigation.
<Style x:Key="TransitioningStyle" TargetType="tcc:TransitioningContentControl">
<Setter Property="Transition" Value="SwingOpen" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="layout:TransitioningContentControl">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="2">
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="SwingOpen">
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"
Storyboard.TargetName="PreviousContentPresentationSite">
<EasingDoubleKeyFrame
KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame
KeyTime="0:0:0.4" Value="90"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="PreviousContentPresentationSite">
<EasingDoubleKeyFrame
KeyTime="0:0:0.3" Value="1"/>
<EasingDoubleKeyFrame
KeyTime="0:0:0.4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation Duration="0"
To="0"
Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)"
Storyboard.TargetName="PreviousContentPresentationSite" />
<DoubleAnimation Duration="0"
To="0"
Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)"
Storyboard.TargetName="CurrentContentPresentationSite" />
10. <Grid>
<ContentPresenter
x:Name="PreviousContentPresentationSite"
Content="{x:Null}"
ContentTemplate="{TemplateBinding
ContentTemplate}">
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
<ContentPresenter.Projection>
<PlaneProjection />
</ContentPresenter.Projection>
</ContentPresenter>
<ContentPresenter
x:Name="CurrentContentPresentationSite"
Content="{x:Null}"
ContentTemplate="{TemplateBinding
ContentTemplate}" >
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
<ContentPresenter.Projection>
<PlaneProjection />
</ContentPresenter.Projection>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In the app.xaml.cs, set the style of the root frame to the new style created in
the previous step.
RootFrame = new PhoneApplicationFrame()
{
// Use a style to use the Template with the TransitioningContentControl
Style = (Style)Resources["mainFrameStyle"]
};
Right now, this is all that one would need to do to implement a transition between pages. However, it
will show the same “SwingOpen” transition navigating forward and back. But, like the transitions in
iPhone, it is a clearer user experience to show a different transition for backward navigation than
forward. This can be accomplished with the following steps:
Extend the TransitioningContentControl class, set up a Setter for the transition
that would be used:
public class CardsTransitioningContentControl : TransitioningContentControl
11. {
private static String _currentTransition = "SwingOpen";
public static void SetBackTransition()
{
_currentTransition = "SwingClosed";
}
public static void SetForwardTransition()
{
_currentTransition = "SwingOpen";
}
protected override void OnContentChanged(object oldContent, object newContent)
{
Transition = _currentTransition;
base.OnContentChanged(oldContent, newContent);
SetForwardTransition(); // reset to the default
}
}
In the PhoneApplicationPage class, capture the back button press and update the
transition
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
CardsTransitioningContentControl.SetBack();
base.OnBackKeyPress(e);
}
Orientation Transitions – Like page transitions, it is up to the developer to implement a transition for
orientation changes. This can be done by overriding the application frame class and registering an event
listener for the OrientationChanged event. The Cards implementation is a simplified version of the
sample from: http://blogs.msdn.com/b/delay/archive/2010/07/13/spin-spin-sugar-updated-code-to-
easily-animate-orientation-changes-for-any-windows-phone-application.aspx. This example is nice
because it will size the content as it rotates providing a fluid transition between states.
First, create a new subclass of PhoneApplicationFrame and have the App.xaml.cs instantiate it when it
creates the frame.
In the InitializePhoneApplication method of App.xaml.cs
RootFrame = new CardsApplicationFrame()
Then fill in the details of the PhoneApplicationFrame subclass
public class CardsApplicationFrame : PhoneApplicationFrame
{
private readonly RotateTransform _rotateTransform = new RotateTransform();
private readonly Storyboard _orientationStoryboard = new Storyboard();
private readonly DoubleAnimation _orientationAnimation = new DoubleAnimation();
private readonly OrientationState _fromOrientationState = new OrientationState();
private readonly OrientationState _toOrientationState = new OrientationState();
private UIElement _clientArea;
private Size _lastSize;
public CardsApplicationFrame()
{
RenderTransform = _rotateTransform;
RenderTransformOrigin = new Point(0.5, 0.5);
13. switch (e.Orientation)
{
case PageOrientation.PortraitUp:
_toOrientationState.Angle = 0;
break;
case PageOrientation.LandscapeLeft:
_toOrientationState.Angle = 90;
break;
case PageOrientation.LandscapeRight:
_toOrientationState.Angle = -90;
break;
case PageOrientation.PortraitDown:
_toOrientationState.Angle = 180;
break;
default:
throw new NotSupportedException("Unknown PageOrientation
value.");
}
// Determine new size
var actualWidth = ActualWidth;
var actualHeight = ActualHeight;
var toPortrait = (0 == (_toOrientationState.Angle % 180));
_toOrientationState.Width = toPortrait ? actualWidth : actualHeight;
_toOrientationState.Height = toPortrait ? actualHeight : actualWidth;
_orientationStoryboard.Begin();
}
protected override Size MeasureOverride(Size availableSize)
{
if (null != _clientArea)
{
// Adjust measure size to transition size
var newValue = (double)GetValue(ProgressProperty);
var width = _fromOrientationState.Width +
(newValue * (_toOrientationState.Width -
_fromOrientationState.Width));
var height = _fromOrientationState.Height +
(newValue * (_toOrientationState.Height -
_fromOrientationState.Height));
_clientArea.Measure(new Size(width, height));
}
// Return default size
return availableSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (null != _clientArea)
{
var newValue = (double)GetValue(ProgressProperty);
var width = _fromOrientationState.Width +
(newValue * (_toOrientationState.Width -
_fromOrientationState.Width));
var height = _fromOrientationState.Height +
(newValue * (_toOrientationState.Height -
_fromOrientationState.Height));
_clientArea.Arrange(new Rect((finalSize.Width - width) / 2,
(finalSize.Height - height) / 2, width, height));
}
return finalSize;
}
private class OrientationState
{
14. public double Width { get; set; }
public double Height { get; set; }
public double Angle { get; set; }
}
}
Networking – The following is an example of a base request class that is used to send an asynchronous
request to a server. It allows for different request methods, and will call handler methods upon
completion of the request.
public abstract class CardsRequestBase
{
…
public void SendRequestToService()
{
String url = GetURL();
_request = (HttpWebRequest)WebRequest.Create(url);
// set any headers like authentication, cache options, etc
SetRequestHeaders(_request);
_request.Method = GetMethod();
// Is it a request that requires data to be added?
if (_request.Method.Equals("POST") || _request.Method.Equals("PUT"))
{
_request.BeginGetRequestStream(new AsyncCallback(SendDataToStream),
_request);
}
else
{
SendRequest();
}
}
private void SendDataToStream(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
Stream postStream = request.EndGetRequestStream(asynchronousResult);
String postData = GetContentData();
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
SendRequest();
}
private void SendRequest()
{
IAsyncResult result = _request.BeginGetResponse(new
AsyncCallback(HandleResponse), this);
ThreadPool.RegisterWaitForSingleObject(
result.AsyncWaitHandle,
new WaitOrTimerCallback(RequestTimeoutCallback), this,
(GetTimeoutSeconds() * 1000), true);
}
protected virtual String GetContentData()
{
return "";
}
protected virtual void SetRequestHeaders(HttpWebRequest request)
{
}
15. private void RequestTimeoutCallback(Object state, bool timedOut)
{
if (timedOut)
{
CancelRequest();
}
}
protected virtual void HandleResponse(IAsyncResult result)
{
try
{
HttpWebResponse response =
(HttpWebResponse)_request.EndGetResponse(result);
using (Stream responseStream = response.GetResponseStream())
{
HandleResponseStream(responseStream);
// extra processing option for subclasses
// this is here to take advantage of performing
// needed operations (like parsing) on the background thread
PostResponseProcessing();
}
}
catch (Exception e)
{
_error = e;
}
if (_requestHandler != null)
{
if (_error == null)
{
_requestHandler.RequestCompletedWithResults(_results, this);
}
else
{
_requestHandler.RequestCompletedWithError(_error, this);
}
}
}
// Broke this out to its own method so that classes can override as needed
protected virtual void HandleResponseStream(Stream responseStream)
{
using (StreamReader reader = new StreamReader(responseStream))
{
_results = reader.ReadToEnd();
reader.Close();
responseStream.Close();
}
}
Data Serialization – The server for Slalom Cards provides a RESTful service for the data that the client
consumes. We took advantage of the XMLSerializer to parse the responses from the server, and to store
data in the Isolated Storage on the device. The service’s responses were in XML, but a JSON response
would be just as easy to handle with the DataContractJsonSerializer class. The following snippets of
code are examples of the use of the XMLSerializer in SlalomCards:
The Collection Class
// Parse a collection of People objects, the root of the collection will be the element "People"
16. // like <People>... people list .. </People>
[XmlRoot(ElementName = "People")]
public class PersonList : ObservableCollection<Person>
{
}
The Person Class: Note the INotifyPropertyChanged interface. This is used to
notify clients, like binding clients of updates. (Like KVO in iPhone).
// Will Parse into a Person Object where the Element name is "P"
[XmlRootAttribute("P",Namespace="", IsNullable = false)]
public class Person : INotifyPropertyChanged
{
private Guid _ID;
private String _action;
public Person()
{
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChanged(String changeProperty)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(changeProperty));
}
}
[XmlAttribute(AttributeName="id")]
public Guid ID
{
get
{
return _ID;
}
set
{
if (value != _ID)
{
_ID = value;
NotifyChanged("ID");
}
}
}
[XmlAttribute(DataType = "string", AttributeName = "ac")]
public String Action
{
get
{
return _action;
}
set
{
if (value != _action)
{
_action = value;
NotifyChanged("Action");
}
}
}
…
17. Reading the PersonList object data from a stream. This could be a HTTP Response
Stream, a File Stream, Memory Stream, etc.
using (stream)
{
// Read the personList object from the stream
XmlSerializer ser = new XmlSerializer(typeof(PersonList));
_personListTable = (PersonList)ser.Deserialize(stream);
}
Data Storage – The Slalom Cards application persists data by taking advantage of data serialization,
isolated storage, and LINQ to fetch, sort, and filter the data. A resource video for developing
occasionally connected applications that was the inspiration for the example can be found at:
http://www.msteched.com/2010/NorthAmerica/WPH306
First create a Singleton for Database Management
sealed class CardsDatabase
{
private PersonList _personListTable = null;
private CardsDatabase()
{ }
private static CardsDatabase _staticDB = new CardsDatabase();
public static CardsDatabase Instance
{
get
{
return _staticDB;
}
}
Then Create the Table members of the Database Class that will fetch the data, (in
the same CardsDatabase class)
private PersonList _personListTable = null;
public PersonList PersonListTable
{
get
{
if (_personListTable == null)
{
using (IsolatedStorageFile store =
IsolatedStorageFile.GetUserStoreForApplication())
{
Stream stream = null;
if (store.FileExists(_personListFile))
{
stream = store.OpenFile(_personListFile, FileMode.Open);
using (stream)
{
// Read the personList object from the stream
XmlSerializer ser = new
XmlSerializer(typeof(PersonList));
_personListTable = (PersonList)ser.ReadObject(stream);
}
}
}
}
return _personListTable;
18. }
}
Finally, create a LINQ query to fetch the data as your application needs it:
PersonList people = CardsDatabase.Instance.PersonListTable;
ListBox.ItemsSource =
from p in people
where p.Office == "Seattle"
orderby p.FirstName, p.LastName
select p;
…
Concluding Thoughts
There are many things with Windows Phone 7 that an iPhone developer will find familiar and be
comfortable with, but a few things that have a bit of a learning curve. Since the capabilities of the
devices are so similar, functionality can be mirrored from iPhone to WP7. However, they are two
different worlds and so there is still work associated with your first ported application. We hope this
article will help clarify some of these differences, and will help you to develop Windows Phone 7
applications in a more efficient, streamlined, manner.