Introduction
In this article, we are going to create our first Windows Phone 7 application running the new "Mango" update. We will start by creating the application in Visual Studio, and then we will analyze the code that makes it up to start to gain some familiarisation with Silverlight and XAML. Once we have grasped the code, we will see how we can quickly modify the generated code to display different text and react to a button click.
Background
Recently Microsoft announced the release of an update[^] to Windows Phone 7, codenamed Mango, which brings a whole raft of top notch functionality to the hands of WP7 developers. It occurred to me that, while there are many great WP7 articles here on CodeProject, there isn't a resource that teaches WP7 development from the ground up. To solve that, it seems that we need a series of articles that try to teach WP7 in a friendly and simple fashion.
These articles don't assume that you have written any WP7, XAML (pronounced ZAMEL), XNA or that you know what Silverlight and XNA are, or how things such as Dependency Properties and databinding work. Hopefully, by the end of the series, you'll have learned enough to be able to tackle developing WP7 applications easily and with confidence.
Some of the articles will demonstrate how to use Expression Blend, but don't worry if you haven't got a copy - I'm just going to be using it for styling parts of the user interface, and you should feel free to copy the templates I'll be producing. The primary tool we'll be using in these articles is Visual Studio 2010. Where we are using Silverlight, we are going to ensure that we follow the guidelines for designing Metro applications. Metro refers to the look and feel of WP7 applications, along with how the application responds; a guiding principle of WP7 application is that it must fit in with the other applications that run on the phone and be easy to get to grips with for somebody who's used to Metro apps, but who hasn't used your application before.
Rather than rehash a lot of what has already been written about the history of Windows Phone 7, I'd suggest that you read this[^] if you are interested in the history of WP7. The points of interest for us is that development on WP7 can be done using a version of Silverlight developed to take advantage of the features of the phone, and a version of XNA (a great API designed for developing games that run on the phone, the XBOX and a Windows PC) to develop games for the phone and by the end of the series of articles, we'll have used both.
Useful Links
You might find the following links useful while you are reading this article.
- The latest version of the WP7 SDK can be downloaded here[^]. It runs on Windows Vista (SP2) or Windows 7 and requires Visual Studio 2010 with Service Pack 1[^] or Visual Studio Express for Windows Phone which can be downloaded here[.].
- Windows Phone Metro Theme information can be found here[^].
- The Metro UI Guidelines can be downloaded here[^].
Prerequisites
I'm assuming that you are familiar with standard .NET and Visual Studio concepts such as namespaces, classes and code-behind files. It's not going to teach you how to code in C# (or VB.NET if that's your language of choice).
Our First WP7 Application
The classic application when getting started is Hello World, and this application is going to be no exception. So, let's buckle up and enjoy the ride into our Windows Phone world by firing up the old Visual Studio.
Once Visual Studio is open, select File > New > Project to display the New Project dialog. In the list of installed templates, look for the section Silverlight for Windows Phone and choose Windows Phone Application (I'm going to use C#, so the templates are installed under the Visual C# node). Let's name it MyFirstPhoneApplication
and click OK to create the application.
If you've installed any previous versions of the WP7 SDK, you'll now see a dialog asking you to choose the platform you want to target. Choose "Windows Phone 7.1".
If all has gone according to plan, we should have a solution that looks like this (don't worry if you don't have the All Open Unsaved Edited part - it's from an addin that I have installed on my development environment):
What are those Funny Looking Files Ending with xaml?
XAML stands for XML Application Markup Language. Basically, in WP7, XAML allows you to lay out user interfaces declaratively, and that's what these files contain. OK, that sounds great but what does it actually mean?
When you create just about any type of user interface, there's an implicit parent-child relationship in there. Typically, you'd have a top level form which would have a collection of child controls. Some of these child controls may contain collections of child controls. Well, XAML allows you to represent this hierarchy using XML to identify the different controls and what they belong to along with some of the properties of these controls. The important thing to remember is that anything you can do in XAML, you can do using straightforward C# or VB.NET (but it is easier to do this in the XAML). But why do we need it? Well, XAML allows designers to layout the user interface without having to know how to write any code and, once you get used to it, it does become very natural to layout your interface in.
OK, You've Told Me What Those Files Are, But What Do They Actually Do?
App.xaml and App.xaml.cs
As you're aware, in order to run an application, we have to have an entry point. Well, in WP7 this is no different, and the entry point is the Application. The default location of the Application class is in these two files (whenever you see .xaml.cs, this tells you that this is a code-behind file for a .xaml file). Let's take our first look at some XAML and see what's in that App.xaml file.
<Application
x:Class="MyFirstPhoneApplication.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">
-->
<Application.Resources>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>
"Whoah Pete. That's some scary looking stuff there." I hear you say. Fear not, for I am here to tell you that this stuff is nowhere near as scary as it looks. Let's break this down and figure out what this all means.
<Application
x:Class="MyFirstPhoneApplication.App"
...
</Application>
Remember that I said this file was based on XML? It may come as no surprise that this file conforms to the rules of XML so the opening tag must have a balancing closing tag. In this case, the tag is Application
, which tells the compiler that this is the XAML containing the Application
definition. The next line simply tells the compiler what the namespace and class name is for this particular file. If you are familiar with ASP.NET, you should recognise this as being similar to the Page
directive at the top of your .aspx file, with the Inherits
tag telling the compiler what the ASPX inherits.
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">
These lines allow you to use functionality present in .NET namespaces directly in the XAML. There are two ways of hooking namespaces in; either by specifying a URI which will have been published as an XML namespace definition in the assembly in question, or by using the clr-namespace
format (the assembly part tells the compiler which DLL the namespace is defined in if it's not in the current assembly). We'll cover namespace definition in more depth in a later article when we look at adding new assemblies and interacting with them in the XAML).
Suffice it to say, if we need to interact with something that's in a namespace other than the default one covered by xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation", then we need to prefix the element with the namespace name we've set up here. An example of an element that's in the default namespace is Application
(which is why it doesn't need to be prefixed with anything).
<!---->
<Application.Resources>
</Application.Resources>
Resources are items that can be reused throughout the XAML such as brushes or templates and styles. We'll cover resources in depth in a later article, but any resources that we want to be usable across any XAML page in the current application would be placed in this section. This saves us having to copy the same elements into different pages - you can almost think of this as being like a CSS file that has been included into every page.
<Application.ApplicationLifetimeObjects>
-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
This section is actually pretty cool because of what ApplicationLifetimeObjects
do for us. Rather than having to subclass the Application
class to add extra functionality, we can use this section to list extensions (yes, they are standard extension methods) that extend the Application
class. WP7 provides a standard extension called the PhoneApplicationService
(note the use of the shell: to tell us that it's in the Microsoft.Phone.Shell
namespace). So, what does this class give us? Well, it provides access to methods that are associated with various aspects of the application's lifetime such as when it's launched. The four that are listed here as attributes (this is the easy way to add properties and events to an object in XAML) relate to the Launching, Closing, Activated and Deactivated events, and the event handlers live in the file App.xaml.cs.
Well, we've seen that there's code linking into the App.xaml.cs file, so what does it look like? Rather than listing the whole file out, let's open up the code in Visual Studio and I'll explain what each bit does.
Phew, that's a lot of code in there, but what does it do. Again, it's easier to understand if we break it down into little bits. This time, we aren't going to cover all the code as we really don't need to discuss the using
statements, the namespace and class definitions. Right, let's look at the RootFrame
property.
public PhoneApplicationFrame RootFrame { get; private set; }
All WP7 pages are displayed inside a frame, and this frame is accessible through this property. If we were to think of this in terms of a browser based application, then the RootFrame
would be the equivalent of the web browser itself, and the pages would be individual HTML pages.
public App()
{
UnhandledException += Application_UnhandledException;
InitializeComponent();
InitializePhoneApplication();
if (System.Diagnostics.Debugger.IsAttached)
{
Application.Current.Host.Settings.EnableFrameRateCounter = true;
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
}
This is the constructor for our App
class, so it's called as soon as the class is initialised. At this stage, there are no visual items created, and nothing to hook into visually, so it's important not to add anything here that relies on visual elements being displayed.
The UnhandledException
line is generally good practice in our applications because it provides a top-level error handler that, in all but the most extreme cases, is guaranteed to be called. The error handler is actually handled in the method Application_UnhandledException
.
If we look in the class, we won't find any implementation for the InitializeComponent
method, but when we compile the code there are no errors here. So what is this? Is there a magical setting in the compiler that doesn't generate compilation errors when it encounters InitializeComponent
methods in the code? Not surprisingly, this isn't the case - the real reason is much more mundane, and the clue lies in the class definition, this is a partial class. When the application is compiled, code is created for us behind the scenes in special .g.cs files, and InitializeComponent
is implemented in this class.
The next line simply calls the InitializePhoneApplication
method defined later on in the class. We'll cover that method shortly.
The next section covers the behaviour of the application when the debugger is attached. Rather than covering them line by line, I'll give you a brief overview here of what these properties are used for (including the commented out properties). At this stage, even though we haven't finished writing our program, let's build and run it. When we run the application, it opens up the windows phone emulator (note the Windows Phone Emulator option in the toolbar).
When the emulator is firing up, it looks like this:
Once the application has loaded, it looks like this:
OK, so that was an interesting little diversion (I hope), but you may be wondering what we are doing here when I promised that I would explain the bits inside the Debugger.IsAttached
section. Well, if you look carefully at the image above, you'll see what looks like interference. If I rotate the image, resize and crop it a bit, we might get a hint that there is something more going on here.
So, what are those numbers? Well, they are the frame rate counters that have been enabled by the line Application.Current.Host.Settings.EnableFrameRateCounter = true;
. From the left, these numbers are:
- The render thread frame rate. This tells us the number of frames per second that is being output on the render thread. If we have a graphically intensive application, we should aim for a frame rate of about 60fps (the lower the number, the less responsive the UI is going to feel).
- The UI thread frame rate. This is the frame rate that the primary UI thread is executing, and manages things such as property change notifications, data binding and animations not handled on the render frame.
- The texture memory usage. This tells us how much video memory is being used to store application textures.
- The surface counter. This shows the number of surfaces being passed to the graphics chip.
- The total number of intermediate textures used.
- The screen fill rate. This describes the number of complete phone screens being painted in each frame.
If we uncommented Application.Current.Host.Settings.EnableRedrawRegions = true;
we would be able to see the items that are being redrawn every frame. If something is been drawn by the GPU, we will not see a redraw here; this is the ideal that we want - redraws being handled by the GPU.
The line Application.Current.Host.Settings.EnableCacheVisualization = true;
is an interesting one. This tells us what is not being redrawn by the GPU by applying a coloured tint to it. If an item is handled by the GPU and cached, it will not be tinted.
The line PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
comes with a big comment warning for a reason. In the standard phone application mode, the idle detection allows the phone to conserve resources and allows it to "hibernate" when the application has been idle for a period of time. If we switched this functionality off in the released version, our application would end up consuming power as it would not go into idle mode.
The Windows Phone GPU - A Sidebar
WP7, in common with most smart phones, supports a graphics processor unit (GPU) which can be used to improve the performance of graphical applications. In general, we can let Silverlight take care of delegating the work to the GPU for us, but there are some rules that must be followed to support this behaviour. Throughout this series, we'll see areas and rules that help us identify whether or not something runs on the GPU.
Now, let's get back to the code.
private void Application_Launching(object sender, LaunchingEventArgs e)
{
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
}
These are the methods that were hooked up as part of the PhoneApplicationService
extensions. In future articles, we'll find out how and why we need to use these methods.
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
}
This method breaks to the debugger, if it's attached, when navigation fails.
private void Application_UnhandledException
(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
}
This is the event handler for coping with unhandled exceptions. In future articles, we are going to delve into making this a more feature rich method, and take a look at how to make the exception handling actually do something meaningful. Suffice it to say, the default implementation only breaks to the debugger if it's attached, which isn't very useful in deployed situations.
#region Phone application initialization
private bool phoneApplicationInitialized = false;
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
phoneApplicationInitialized = true;
}
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
if (RootVisual != RootFrame)
RootVisual = RootFrame;
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
#endregion
}
}
The final piece of the App.xaml.cs puzzle lies in these two methods. The use of the field phoneApplicationInitialized
is there to guard against this method being called twice. The RootFrame
property is initialized and the Navigated
and NavigationFailed
events are hooked up. Finally, the root visual object is set to be the root frame and the navigated event is dereferenced.
That's almost it for the App.xaml files. There's one final piece of the jigsaw to sort out, how does the application know that the App
class is the startup? Well, if we open up the project properties dialog and take a look in the Application tab, we can see that the startup object is set to MyFirstPhoneApplication.App
. Now it's time to take a look at the MainWindow
functionality.
MainPage.xaml
Let's take a look at the contents of MainPage.xaml. Don't worry if it looks cryptic at the moment, as we are going to break it down and discuss the different parts and see how they all fit together.
First of all, let's look at the actual code.
<phone:PhoneApplicationPage
x:Class="MyFirstPhoneApplication.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>
Well, that looks fairly scary, but you'll be pleased to know that it is actually fairly easy to understand.
<phone:PhoneApplicationPage
x:Class="MyFirstPhoneApplication.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"
...
</phone:PhoneApplicationPage>
Just as in the App.xaml file, the opening attributes set up the class behind the XAML and add in the appropriate namespaces for use in the XAML. As we can see here, the phone pages inherit from the PhoneApplicationPage
type which is the equivalent of an HTML page in a browser, or a Form
in a WinForms application.
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
These attributes are interesting. The d:
attributes are Expression Blend tags, and tell the design window what width and height to apply to the page. These sizes could be different from the real width and height of the page, if we wanted to - they are just set to help the UI designer lay out the screen. The mc:Ignorable
tag tells the compiler to ignore any namespace that starts with d:
in the XAML. Don't worry if this doesn't make too much sense right now; it will become clearer when we start to use the design window more.
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
Right, this is going to take a little bit of explaining, so please excuse me while we divert into resources territory.
As you're no doubt well aware, Windows applications allow us to embed resources into applications which we can access in use. Well, WP7 based applications are no different - we can embed resources and access the individual resource quite easily. In Silverlight applications, we use something called a ResourceDictionary
to manage our resources. Now, the syntax to access the resource items looks a bit funny, but we have to get used to it because we will use this a lot. Basically, the StaticResource
markup tells the compiler that it needs to look something up from a ResourceDictionary
and apply it. The use of the {} symbols tells the compiler that it is going to have to bind a value in rather than just apply a string
literal.
The values for the different resources here are obtained from the standard resource for the phone, so we don't need to add these values ourselves. Details of these resources can be found here[^].
While we could have set the FontFamily
to Segoe UI using FontFamily="Segoe UI"
, the fact that we are using the resource dictionary means that we only need to change the dictionary and recompile it if we want to change the font to Verdana. I didn't just pick Segoe UI here either, this is the current value of PhoneFontFamilyNormal
in the resource dictionary. Where possible, using resource dictionaries is a good habit to get into because of how easy it is to change elements that are being reused; in this respect, they are just like constants.
SupportedOrientations="Portrait" Orientation="Portrait"
These two attributes tell the phone how to display this page when it's viewed (Orientation
), and whether it can be displayed in Landscape or Portrait as well (SupportedOrientation
).
shell:SystemTray.IsVisible="True">
The system tray is a handy item at the top of the phone display that the user can tap to gain access to information such as the signal strength and battery life. By setting the visibility to true, the user has access to this functionality. We should only change this if we are really sure that your application should not display the system tray because the users are used to it being present.
The following diagram highlights the system tray in red:
<!---->
<Grid x:Name="LayoutRoot" Background="Transparent">
...
</Grid>
Finally we're getting to the part where visual items are being added. When we want to add controls that are displayed, we need to add them to something that tells the application how to lay out the components. In this particular case, we have a Grid
which behaves in a similar fashion to a Table
control in HTML, in that it can be used to lay controls out in rows and columns. The attribute x:Name
gives the grid a name which can be used by the code behind to get access to the grid and manipulate it if we need to. Finally, the Background
attribute here makes the grid transparent.
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
Rather than having to use a <TR>
style of syntax to define rows in a table in the way that you would with HTML, XAML allows us to define the rows up front, which is an incredibly powerful feature that we will explore more as we go through the series because it allows us to just change a single value on a control to say where it's displayed. This is an incredible time saver if we are hand editing the XAML as we don't have to cut and paste items to move them into new rows. We will use this feature when we are modifying our application.
The Height
attribute tells the application how big to make the row, but what are those funny sizes? When the height is set to Auto
, the size of the row is based entirely on how big the content is. When the height is referenced as a *
, it means that the size is a proportion of the available space, and you will sometimes hear this referred to as star sizing. In this particular case, it means that it uses all the remaining space.
Note: If we don't supply this section, an implicit row definition is added to our grid that takes up the whole size of the grid.
<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>
The first row of the grid is going to container another control container. This time, it contains something called a StackPanel
which tells the application to position controls on separate lines, or all on the same line. By nesting containers, we can create flexible layouts with a minimum of fuss. Again, we'll do a lot more of this throughout the series, so we'll get plenty of practice using the different types of containers. The Grid.Row
attribute is an interesting one. If we go to the documentation for the StackPanel
and search all night, we won't find any references to Grid.Row
on there. Is this an omission on Microsoft's part? Well, while the MSDN is occasionally apocryphal, it's not wrong in this case. Grid.Row
is a wonderful thing called an attached property, which we can think of as being a global property that can be attached to any type of object, and it helps control the behaviour of the object. In this case, it tells the grid to position the StackPanel
in the first row (note that this is zero based).
The Margin
is used to control the space between elements.
Now we actually get to some elements that the user can see. In the XAML, we have two TextBlock
controls which display the text from the Text
attribute.
The last markup in the file is commented out, and we will cover this in a later article when we add an application bar to our application.
Okay, we've covered the boilerplate code in quite some depth, and you are probably itching to get your hands dirty. Well, itch no more, we're going to add some code for ourselves.
Hello World
The first step is to open up MainPage.xaml in Visual Studio. We are going to use the design window rather than edit the XAML directly. If you've never used the designer window, you can get to it using the Design tab (highlighted in red below):
First of all, let's change the text MY APPLICATION into Hello World. Make sure that the Properties tab is open, then click on the text in the design view and the TextBlock
that contains it is selected.
The Properties tab should look something like this:
Right, change the text to read Hello World. Then select the page name and remove the text from the Text
property. At this stage, our phone application should look like this in the designer:
Now we're going to add a button to the application. Open up the Toolbox and double click on the button control. This adds the button to the top left corner of the phone designer.
Not very attractive is it? Well, we're about to see exactly what that grid row property does. In the properties window, scroll down until you can see the Grid.Row
property.
Change the value of to 1
, and be amazed as the button moves to the next row. Rather than showing you a screenshot of this stage, let's set a couple of other properties. Set both the HorizontalAlignment
and VerticalAlignment
properties to Center
to move the button. Once you have done this, double click the button to create an event handler in MainPage.xaml.cs, and in the code that's generated, add the following code:
PageTitle.Text = "BOO !!!!";
This line of code sets the text to be displayed in the TextBlock
called PageTitle
.
Finally, compile the application and run it. It should look like this:
Now press the button and watch the BOO !!!! appear.
The XAML that accomplishes this magic looks like this:
<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="Hello World"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
<Button Content="Button"
Height="72"
HorizontalAlignment="Center"
Margin="10,10,0,0" Name="button1"
VerticalAlignment="Center" Width="160" Grid.Row="1"
Click="button1_Click" />
</Grid>
The most interesting part of that particular code lies in the line Click="button1_Click"
. This ties the click event of the button up to the button1_Click
method in MainPage.xaml.cs.
That's it, we've created our first WP7 application using both XAML and code-behind that hooks up to the controls defined in the XAML.
As you can see, adding and editing controls in the designer can be a very simple task; the changes we made to the application were accomplished quickly and with the minimum of effort. Once you become comfortable with the tooling, creating XAML can be a relatively painless process, as evidenced by the speed we have managed to modify the code to do what we want.
A final question to ponder. How does the phone know that MainPage
is the page to display? After all, there's nothing immediately apparent in the XAML or the code behind to tell the compiler to mark this page, and there's no reference to it in App.xaml. The answer lies in the file WMAppManifest.xml which creates a task that points to MainPage
. We aren't going to cover this file in any depth in this article, but we will come back to it in a future article when we see how it affects pinned and live tiles.
What Have We Learned?
In this article, we have created our first WP7 application using Visual Studio, and modified it to display Hello World. Along the way, we have analysed the basics of a XAML application, and started to see how code behind and XAML fit together. Finally, we changed the project to display Hello World and react to a button click.
In future articles, we will expand on the knowledge we have gained here and really start to get a deeper understanding of WP7 development.
Further Reading
The following books could be of some assistance while learning WP7:
- 101 Windows Phone 7 Apps, Volume I by Adam Nathan[^]
- Professional Windows Phone 7 Application Development: Building Applications and Games Using Visual Studio, Silverlight, and XNA by Nick Randolph and Christopher Fairbairn[^]
- Microsoft Silverlight Edition: Programming Windows Phone 7 by Charles Petzold[^]
- Pro Windows Phone 7 Development by Rob Cameron[^]
- Programming Windows Phone 7 by Charles Petzold (this one's free)[^]
Thanks
I'd like to thank Hans Dietrich, Keith Barrow, DaveAuld, Tom Deketelaere, gavindon and all the other great CodeProject members who have offered their invaluable help in the crafting of this article. If I've forgotten anybody, the fault is mine and mine alone and I apologise unreservedly. Please let me know if I have missed you out and I'll update the list accordingly to reflect your diamond status.
Critique
Please, if you feel this article doesn't meet your needs, or that there are things in here that you don't understand or that I haven't explained clearly, please let me know. Your input into this series is invaluable. Please don't worry if you can't remember the syntax or the concepts clearly, we will be covering each area in much more depth as we progress through the series.
History
- July 2011 - Initial version