This article is part 2 in a 12-part article series on Windows Phone 7 for iPhone and Android Developers.
In the first article in this series we walked through some sample code that illustrated how to use C# to create classes that inherited from other classes, defined properties, and even implemented interfaces. As fantastic as that may be on its own, it certainly isn’t going to make for an impressive (or even visible) demo.
This article aims to show you how to get started constructing the user interface of your Windows Phone 7 application with a slight bent toward easing the UI-building transition from iOS and Android. As with all articles in this series, you don’t need any iOS or Android experience to learn from article, but iOS and Android developers may find that this series of articles makes learning WP7 a little easier than generic tutorials.
Most modern programming environments allow developers to visually construct their UI with the aid of a design tool. Visual Studio and Expression Blend both allow for visual construction of Windows Phone 7 UIs and Interface Builder lets you build iOS interfaces visually. Underneath the hood of the design tool is typically some form of intermediate language that is then converted into executable code. Sometimes this intermediate form is so nasty to look at that developers never interact with it.
For iOS, Interface Builder stores all the properties and settings and object hierarchies constructed by the developer in the form of a human-antagonistic XIB file, which is an XML serialization of object graphs. Despite XML’s claim of human readability, XIB files are rarely ever examined by developers. Android uses a specific subset of XML to represent subclasses of Views and their associated properties. And the subject of this article, Silverlight, uses Xaml to declaratively instantiate user interface elements.
Introducing Xaml
Unlike some other visual design languages that are an intermediate layer between the code and the design surface, Xaml (eXtensible Application Markup Language) is the code. When teaching people about Xaml, Silverlight, and Silverlight’s big brother WPF (Windows Presentation Foundation) I am often shocked that many people who have been using Xaml for a while aren’t aware of it’s true nature or power.
Take a look at this snippet of XML from an Android “hello world” application:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Okilly-dokilly! - Nedward Flanders, Jr."/>
In this little bit of XML, you see an XML element that shares the name of a view and properties on this XML element that are eventually mapped to properties (or get/set accessors in Java’s case since it really has no native property support like C# or Objective-C). A subtle but vitally important distinction here is that the subset of XML that is considered valid for Android is limited only to that which is defined in the Android schema. In short, Android uses XML as an intermediate or mapping medium. A part of the compilation reads the XML, performs some translation, and generates Java.
Xaml is an instantiation language as opposed to an intermediate or translational medium. As I said, the XML in a Xaml document isn’t being converted piecemeal into code by a bunch of fixed, shrink-wrapped logic, it is code. If you create an empty Windows Phone 7 project, the contents of your MainPage.xaml file looks like this:
<phone:PhoneApplicationPage
x:Class="IntroToXaml.MainPage"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
</Grid>
</phone:PhoneApplicationPage>
The first thing you should notice is that there are multiple XML namespace identifiers being declared in the topmost element but there’s something different about them. Instead of a traditional namespace identifier, some of these are prefixed with the clr-namespace moniker. Whenever you see this, an XML namespace identifier is being mapped directly to a CLR namespace. The CLR is the Common Language Runtime, the plumbing that makes all C# applications (including Silverlight and WP7) work. You can think of this as having a similar purpose as the JVM (Java Virtual Machine).
The element <phone:PhoneApplicationPage> is actually declaring an instance of the class PhoneApplicationPage. If you look at the XML you’ll see the namespace identifier phone is part of the CLR (.NET) namespace Microsoft.Phone.Controls. So we know from this Xaml that the root object is actually an instance of Microsoft.Phone.Controls.PhoneApplicationPage. This class has properties on it that are set declaratively in the Xaml such as FontFamily and FontSize and Foreground.
Like so many other Silverlight controls, the PhoneApplicationPage control uses the first child element declared as it’s Content property so in the preceding listing, we know that the instance of the Grid control is actually going to be set as the page’s content. This isn’t done by a translator or parser, this is done because the Xaml is actually creating an object graph of live instances declaratively.
To prove to you, beyond a shadow of a doubt, that you can create an instance of anything in Xaml and that it isn’t just limited to the set of controls that ship with the SDK (like the Android XML dialect), I’m going to use the following code to add an instance of my Zombie class to the page’s Resources dictionary (you don’t need to know much about the resource dictionary right now, we’ll see more of that in future articles).
<phone:PhoneApplicationPage
x:Class="IntroToXaml.MainPage"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IntroToXaml"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
<local:Zombie x:Key="myZombie"
Hitpoints="12"
Name="Kevin"
OozeColor="Purple">
<local:Zombie.Weapon>
<local:Shotgun DamageClass="10" RemainingAmmo="42"/>
</local:Zombie.Weapon>
</local:Zombie>
</phone:PhoneApplicationPage.Resources>
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
</Grid>
</phone:PhoneApplicationPage>
Take a look at lines 16 through 25. The same way the phone:PhoneApplicationPage Xaml element created an instance of Microsoft.Phone.Controls.PhoneApplicationPage, the local:Zombie element creates an instance of IntroToXaml.Zombie, a class that I created. Further, this class has a property called Weapon and you can see that I’m setting that property to an instance of the Shotgun class.
This is the true power of Xaml. Xaml isn’t just a declarative UI XML dialect, it is a generic, all-purpose XML dialect that allows for the direct instantiation of any object hierarchy. In fact, Xaml is also used to declaratively design workflows for the current version of Workflow Foundation (WF) and can be used for a variety of other uses.
In case you still doubt my words and think I’m making this all up, take a look at the code-behind for the MainPage.xaml : MainPage.xaml.cs:
using System.Windows;
using Microsoft.Phone.Controls;
using System.Diagnostics;
namespace IntroToXaml
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Zombie kevin = this.Resources["myZombie"] as Zombie;
Debug.WriteLine(kevin.Name);
Debug.WriteLine(kevin.Weapon.DamageClass);
}
}
}
Here you can see that I am able to obtain a reference to the instance of Zombie that I created declaratively in the Xaml by pulling it out of the page’s resource dictionary. Not only that, but the Debug statements prove that I can traverse the Weapon property to get at the nested properties like DamageClass, further illustrating that any object hierarchy can be represented in Xaml regardless of complexity. As you’ll see later in this article series, the fact that Xaml is code comes in handy when binding UIs to data and vise versa.
So, to recap what we’ve discussed so far as concisely as I can: You use Xaml to declaratively construct Silverlight-based user interfaces for Windows Phone 7. Xaml is not just human-friendly, but can also be generated and read by graphical design tools like Visual Studio and Expression Blend. While Xaml may be an all-purpose language capable of instantiating everything from Zombies to TextBoxes, this article is all about the GUI.
And on that note, without further ado, let’s take a tour of the stock UI controls that come with the Windows Phone 7 SDK and how to declare and configure them using Xaml. If you want to learn how to construct the same UIs visually and without much typing, then I suggest you take a look at some of the Expression Blend tutorials floating around the web (after you finish reading this article, of course).
A Tour of the Stock Controls
Every GUI development platform comes with a stock set of controls that form the building blocks upon which your UI is created and Windows Phone 7 is no different. The following sections of this article will take you on a tour of some of these stock controls. When you get to the end of this section, you should have a fairly good idea of the types of UI elements that you can use to compose your Windows Phone 7 UIs and you’ll be ready for the next article in the series to build on your newfound UI construction prowess.
Display Controls
This next section takes you on a relatively brief tour through some of the controls responsible for displaying non-interactive information to users (note that you can still make these controls respond to touch events, but they don’t work like input controls or buttons). Don’t worry if it feels like we’re skimming over a lot of material, we will see a lot more of these controls in subsequent articles in this series.
The ProgressBar control, as its name implies, displays a visual indication of progress to application users. No UI framework is complete without such a control. One thing that is often overlooked with this control is that you can use it to either display a portion of finite progress (such as number of bytes downloaded out of a known maximum, number of tasks completed, percent of work done, etc) or you can use it to display a set of animated dots that smoothly flow from left to right, indicating that an indeterminate amount of work is currently taking place. This is similar to the Android progress bar control which has an isIndeterminate()/setIndeterminate() accessor pair to control this behavior. iOS, on the other hand, has two separate controls: UIProgressView to display finite progress and UIActivityIndicatorView to display the “spinner” indicating indeterminate progress. Android’s progress bar can also display secondary progress. To do this in WP7 or iOS, you would just use two differently styled and sized progress bars.
You can draw simple shapes such as the Ellipse or Rectangle and these should be fairly easy for you to pick up, especially if you’ve done any drawing with the UIBezierPath class in iOS. You can wrap any visual element with a visible and styled border just by putting that visual element within a Border object.
Take a look at this screenshot illustrating a border. Inside that border is an ellipse, a rectangle, an image, and a TextBlock used for rendering text to the screen. I’ve used a stack panel to arrange the contents of the Border. I take you on a tour through the layout controls in the next section.
Here’s the Xaml that produced the preceding screenshot:
<Border BorderBrush="Yellow" BorderThickness="10" Background="White">
<StackPanel>
<Ellipse Width="200" Fill="Tomato" Height="100"/>
<Rectangle Width="200" Fill="Blue" Height="100"/>
<Image Source="/IntroToXaml;component/appbar.favs.addto.rest.png" Height="50" Width="50"/>
<TextBlock Text="Hello World" Foreground="Black" Margin="15"/>
</StackPanel>
</Border>
Remember that Xaml is just an instantiation language, so every time you see an element you’re creating an instance of an object. Knowing this makes it very easy to programmatically manipulate the objects instantiated by your Xaml at runtime.
To produce this kind of nesting in an iOS application, you really only have two options: meticulously use Interface Builder to control the nesting of sub views or manually create the view hierarchy yourself programmatically with Objective-C. Even then, you’ll find that you don’t have really easy access to primitive shape classes like WP7’s Ellipse or Rectangle. Displaying text is easy regardless of the platform you’re using and you can think of WP7’s TextBox class as being functionally equivalent to the iOS UILabel class.
Layout Controls
As you start writing your own WP7 applications, you will notice that one of the things you spend the most time doing is laying out all of the primitive elements on your pages. There are three main controls that come with the SDK that you will be using for control layout: the Canvas, the StackPanel, and the Grid.
Canvas
The Canvas control provides you with the most basic layout capability : child controls of the Canvas are laid out using fixed position coordinates. In other words, every child control laid out on a Canvas has an X and Y coordinate that corresponds to a relative offset from the origin of the Canvas. You can create some very interesting effects by nesting Canvases within Canvases or nesting one type of layout control within another. You will frequently see StackPanels contained within Grids and vise versa.
Here’s an example of some controls laid out in a fixed-position coordinate system using a Canvas:
<Canvas>
<Border BorderBrush="Tomato" BorderThickness="8" Canvas.Top="50" Canvas.Left="85" Canvas.ZIndex="1">
<TextBlock Text="HELLO" Foreground="Black"/>
</Border>
<Rectangle Fill="AliceBlue" Canvas.Top="30" Canvas.Left="50" Height="100" Width="200"/>
<Ellipse Canvas.Left="100" Canvas.Top="350" Height="100" Width="100" Fill="Bisque" Stroke="Azure"/>
</Canvas>
As an exercise for you, paste this into a WP7 page and see what the end result looks like. Change the Canvas.ZIndex attribute on the border and see how it changes the overall rendering of the container.
If you’ve been programming in iOS then you’re pretty much used to this kind of layout. There are no stock controls in UIKit that allow for flowing, dynamic layout like the StackPanel.
StackPanel
The StackPanel control lays out its child controls much the way its name describes: in a stack. You can control the orientation (either Horizontal or Vertical) but the end result is that the child controls are stacked on on top of each other. One thing you should try playing with is changing the order in which the child controls are declared to see how that affects the way the controls render in the container.
Here’s an example of a typical pattern of displaying labels and data values corresponding to those labels using nothing but nested StackPanels and TextBlock controls:
<!-- default orientation is vertical stacking-->
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Favorite Color:" Margin="10" />
<TextBlock Text="BLUE" Foreground="LightBlue" FontWeight="Bold" Margin="10"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Favorite Weapon:" Margin="10" />
<TextBlock Text="CHAINSAW" Foreground="Tomato" FontWeight="Bold" Margin="10"/>
</StackPanel>
</StackPanel>
As a developer who spent an awful lot of time building user interfaces for the iPhone and iPad, having access to a dynamic layout control like the StackPanel was like getting an early Christmas present!
As for Android developers, the FrameLayout class can be replicated with a single stack panel (or even just a border) set to the same size as the page. LinearLayout corresponds almost exactly to the purpose of the StackPanel control allowing for both horizontal and vertical stacked (linear) layout.
Grid
The Grid control does what you might imagine it to do: lay out child controls according to rows and columns. You can configure the size and number of the rows and columns and you can achieve some pretty slick layouts with creative use of child elements that can span multiple rows and/or multiple columns. You can even nest grids within each other if you like. Android developers used to the TableLayout control will be right at home using the Grid control. As mentioned before, there are no dynamic layout controls available in the stock set of controls for iOS (though you can get close with a couple of them).
Interaction Controls
In the interest of saving you both time and eye strain, I am going to provide a very quick overview of the stock Windows Phone 7 controls that are designed to interact with the user. As mentioned earlier, future articles in this series will delve into further detail on these controls and you’ll see them in future downloadable code samples.
- Button – This is your basic button that responds to Click events. One of the fun things that I like about this control is that it can contain child controls, allowing you to stuff images and text and even other layout controls all within a button. As with most things here, the boundaries of good taste, common sense, and decent UI design should limit your use of these “creative” buttons.
- Checkbox – A standard checkbox control for giving users the ability to toggle information between a true/false or on/off state.
- HyperlinkButton – A button that presents itself as a hyperlink. You can execute your own code in response to the tap and you don’t need to actually open a browser (though opening a browser is extremely easy to do using this control).
- ListBox – An interactive control used to present the user with a scrollable list of items that can be individually selected. iOS programmers familiar with creating UITableViewControllers will recognize a lot of the functionality exposed by this control.
- PasswordBox – A text input control that masks the input characters tapped by the user to prevent password exposure.
- ScrollViewer – A control that wraps its child controls in a scrollable container. You can scroll anything within this viewer and I have even seen this control used to make scrollable regions for casual Silverlight games.
- Slider – A control that allows a user to drag a knob from left to right and easily select some value within a numeric range without actually having to key in numeric values. Judicious use of these controls can often dramatically increase the ease of data entry in user input forms.
- TextBox – A control that allows for a user to input text. You can further limit the type of information that can be entered into this control by changing the type of soft keyboard that appears when the text box has focus.
- RadioButton – A standard control that allows the user to select only one choice from among a list of options.
When you combine this arsenal of interactive controls with the various layout panels and display controls, what you can accomplish on the phone is limited only by the size of the screen and the size of your imagination.
Additional Controls
There are some other interesting controls that come with the SDK that you will probably encounter at some point in the future as you build your WP7 applications:
- Map – This control lets you embed Bing maps into your application with an amazing amount of flexibility. I have an entire article coming up in this series devoted to the use of Bing maps.
- WebBrowser – This control lets you embed an interactive web browser in your application. You can use this to view local HTML content stored by your application or to view Internet websites and you can respond to
- MediaElement – This control allows your application to embed video or audio clips directly in the application, allowing you to access media that is stored locally as part of the application or on the Internet.
What’s Next?
There are a lot of controls and UI elements that come with the base SDK for Windows Phone 7 and learning Xaml for the first time only adds to the potential confusion. One exercise that I think is invaluable to any WP7 newcomer, regardless of the platform with which you are most familiar, is tinkering.
Open up Visual Studio and create a new WP7 application. Then, with reckless abandon and without regard for personal safety, start dragging controls onto the design surface from the Toolbox. Pay attention to the Xaml that appears every time you drag a new control onto the surface. Play around with setting and changing the properties, change colors and sizes and margins and borders and everything else you can do.
While you won’t end up with a contender for most amazing application ever, you will gain a lot of valuable hands-on experience just from tinkering with all the stock controls. The next time you ask yourself, “I wonder how I can represent this in a WP7 UI?” you will remember your tinkering experience and you’ll be able to cobble together some of the things you tinkered with and turn them into a productive UI.
So go, tinker, play, break things and learn. Look at how the Xaml affects the control and then play around with changing control properties from your code-behind in C# and changing them from within Xaml. The difference between experts and rookies lies not in knowledge but in experience. The experts are the ones who have tinkered with everything, broken it all, and put it all back together again.
The next article in this series will show you a few more advanced controls and show you how to start binding your user interface to data – a key part of any nutritious breakfast … or well-balanced application.
About the Author
Kevin Hoffman (http://www.kotancode.com/) is a Systems Architect for Oakleaf Waste Management (http://www.oakleafwaste.com/), freelance developer, and author of multiple books including the upcoming WP7 for iPhone Developers and co-author of books such as ASP.NET 4 Unleashed and SharePoint 2007 Development Unleashed. He is the author of the Kotan Code blog and has presented at Apple's WWDC twice and guest lectured at Columbia University on iPhone development.