As mentioned in the first post in this series, I am launching a series of intensive WP7 tutorials. To get started I thought it was important to revisit this earlier post and make sure all the code is up to date.
[ Note, the intent is not to suggest that writing for the phone is the same as writing for the PC; they are very different platforms (see, for example, my discussion of TransMedia) but only to demonstrate that many of the coding skills you have as a Silverlight programmer will carry over, making the learning curve a good bit flatter ]
On Thursday, August 14, John Papa will air an episode of Silverlight TV in which we examine the premise that Silverlight Programmers are instant WP7 programmers. To demonstrate this, I created two applications side by side: a traditional Silverlight (Web) application and a WP7 application using the same code. (This refresh article brings the code up to the Beta release).
I’ll go through this step by step here, so that you can see the details that go by a bit quickly in the video. I’ll also bring the two programs into even closer alignment…
My friend Jimmy had a cartoon on his wall some years ago that showed a hot dog standing at the mailbox in front of his suburban home. The hot dog was wearing pants and a sports shirt, had a moustache and an astonished look on his face as he read the letter in his hands. The caption was “You May Already Be A Weiner!” |
What comes out of the box.
To get started we’ll open two Visual Studio 2010 applications. In the first, we’ll click on the Silverlight Themes and choose Silverlight Application and then in the second instance of Visual Studio we’ll click on the Silverlight for Windows Phone themes and choose Windows Phone Application,
![]() |
![]() |
Start by opening the App.xaml file in the web version and place the following styles within the Resource tags. Place the same styles in the same spot within the Phone application.
<Style x:Key="PromptStyle" TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Margin" Value="5" /> <Setter Property="FontSize" Value="18" /> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="Grid.Column" Value="0" /> </Style> <Style x:Key="ValueStyle" TargetType="TextBox"> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Margin" Value="5" /> <Setter Property="FontSize" Value="18" /> <Setter Property="FontWeight" Value="Normal" /> <Setter Property="Grid.Column" Value="1" /> <Setter Property="MinHeight" Value="20" /> </Style>
Our next step is to create a form page in each application. Create a new Silverlight Child Window in the web application and a new Windows Phone Portrait Page in the phone version, and name each Form 1.We want to add a grid to each. In the case of the child window in the web version, within LayoutRoot, replacing the row definitions already in place; in the case of the phone application, in the ContentGrid (both grids are created by Visual Studio)
<Grid.ColumnDefinitions> <ColumnDefinition Width="2*" /> <ColumnDefinition Width="3*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> <RowDefinition Height="1*" /> </Grid.RowDefinitions>
Creating the Prompts and Text Boxes
We’ll begin by adding a prompt and a text box for the first name. (Take care that the code goes inside the inner grid in the Phone application)
<TextBlock Text="First Name" Grid.Row="0" Style="{StaticResource PromptStyle}" MaxHeight="Infinity" /> <TextBox x:Name="FirstName" Width="220" Grid.Row="0" Text="{Binding Path=FirstName}" Style="{StaticResource ValueStyle}" />
A few quick things to note:
- Each uses its appropriate style that was added to App.xaml.
- The TextBox sets its width (the prompt will be set to auto by the style)
- The TextBox also sets its contents via Binding
The next block of code goes directly below the code you just added, to provide the remaining prompts.
<TextBlock Text="Last Name" Grid.Row="1" Grid.Column="0" Style="{StaticResource PromptStyle}" /> <TextBox x:Name="LastName" Grid.Row="1" Width="220" Style="{StaticResource ValueStyle}" Text="{Binding Path=LastName}" /> <TextBlock Text="Address" Grid.Row="2" Grid.Column="0" Style="{StaticResource PromptStyle}" /> <TextBox x:Name="StreetAddress" Grid.Row="2" Grid.Column="1" Width="220" Text="{Binding Path=Street}" Style="{StaticResource ValueStyle}" /> <TextBlock Text="City" Grid.Row="3" Grid.Column="0" Style="{StaticResource PromptStyle}" /> <TextBox x:Name="City" Grid.Row="3" Width="220" Style="{StaticResource ValueStyle}" Text="{Binding Path=City}" /> <TextBlock Text="State, Zip" Grid.Row="4" Style="{StaticResource PromptStyle}" /> <StackPanel Grid.Row="4" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal"> <TextBox x:Name="State" Width="90" Text="{Binding Path=State}" Style="{StaticResource ValueStyle}" /> <TextBox x:Name="Zip" Width="120" Text="{Binding Path=Zip}" Style="{StaticResource ValueStyle}" /> </StackPanel> <TextBlock Text="Email" Grid.Row="5" Grid.Column="0" Style="{StaticResource PromptStyle}" Margin="5" /> <TextBox x:Name="Email" Style="{StaticResource ValueStyle}" Grid.Row="5" Width="220" Text="{Binding Path=Email}" />
Visual Studio creates the child window with OK and Cancel buttons, please remove them.
The DataSource
To have data to bind to, we’ll create a Customer class and give it a static method that will provide valid, if simulated data. To do so, in each project right click on the project in Solution Explorer and choose Add Class. Name the file Customer.cs. The Customer class in both projects is identical:
public class Customer : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public Customer( string firstName, string lastName, string street, string city, string state, string zip, string email ) { FirstName = firstName; LastName = lastName; Street = street; City = city; State = state; Zip = zip; Email = email; } public string FirstName { get; set; } public string LastName { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } public string Email { get; set; } private void OnPropertyChanged( string propertyName ) { if ( PropertyChanged != null ) { PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) ); } } public static Customer RandomCustomer { get { return new Customer( "George", "Washington", "1 Federal Plaza", "New York", "NY", "11214", "[email protected]" ); } } }
The class consists of nothing, for this demo, except public automatic properties, a constructor and a static property to return an instance of a Customer.
You can simplify the using statement, in both projects, to a single line:
using System.ComponentModel;
I’ll leave out the event handling for our Form class, being content to load the form with bound data, but we do need a way to get from the first page to the second. Add a button to each MainPage.xaml (in the web form, you can add this right into LayoutRoot, in the Phone you’ll add it to ContentGrid).
<Button x:Name="ChangePage" Content="Form" Foreground="Navy" FontSize="32" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" />
To make the text of the button more visible on the phone, change Foreground from Navy to White.
Changing Pages
The event handler for the Web application will instantiate the child window and “show it." Here is the complete MainPage.cs file,
using System.Windows; namespace SL_YouMayAlreadyBe { public partial class MainPage { public MainPage() { InitializeComponent(); ChangePage.Click += ChangePageClick; } void ChangePageClick(object sender, RoutedEventArgs e) { var wind = new Form1(); wind.VerticalAlignment = VerticalAlignment.Top; wind.Margin = new Thickness(0, 50, 0, 0); wind.Show(); } } }
The event handler for switching to the child window in the WP7 application can either set the RootVisual (declared in App.xaml.cs) or it can invoke the static Navigate method of the NavigationService
using System; using System.Windows; namespace WP7YouMayAlreadyBe { public partial class MainPage { public MainPage() { InitializeComponent(); ChangePage.Click += ChangePageClick; } void ChangePageClick(object sender, RoutedEventArgs e) { throw new NotImplementedException(); } } }
or if you prefer, the body of ChangePageClick can be changed to:
NavigationService.Navigate( new Uri("/Form.xaml", UriKind.Relative ) );
The Bottom Line
There is no doubt that as you dive deeper into WP7 you’ll run into differences between creating Silverlight applications for the web and for the phone, but these are (and will be) well documented and relatively rare. As an experienced Silverlight developer you are, really and not just hype, an experienced Windows Phone 7 developer. That means that rather than concentrating on syntax or on the API, you can focus on the design of your application.
My relatives every time say that I am killing my
time here at net, but I know I am getting familiarity everyday by reading thes
good articles.
Nice Post!
Thx 4 the info