Click here to Skip to main content
Click here to Skip to main content

Peeling the Mango - Win Phone 7 Programming from the Ground Up (Part 1)

By , 14 Jul 2011
Rate this:
Please Sign up or sign in to vote.
Prize winner in Competition "Best overall article of July 2011"

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.

New project dialog.

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".

Choose target Windows Phone platform.

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):

MyFirstPhoneApplication solution expanded.

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.Resources>

  <Application.ApplicationLifetimeObjects>
    <!--Required object that handles lifetime events for the application-->
    <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>
  </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>
    <!--Required object that handles lifetime events for the application-->
    <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()
   {
      // Global handler for uncaught exceptions. 
      UnhandledException += Application_UnhandledException;

      // Standard Silverlight initialization
      InitializeComponent();

      // Phone-specific initialization
      InitializePhoneApplication();

      // Show graphics profiling information while debugging.
      if (System.Diagnostics.Debugger.IsAttached)
      {
        // Display the current frame rate counters.
        Application.Current.Host.Settings.EnableFrameRateCounter = true;

        // Show the areas of the app that are being redrawn in each frame.
        //Application.Current.Host.Settings.EnableRedrawRegions = true;

        // Enable non-production analysis visualization mode, 
        // which shows areas of a page that are handed off to GPU with a colored overlay.
        //Application.Current.Host.Settings.EnableCacheVisualization = true;

        // Disable the application idle detection by setting the 
        // UserIdleDetectionMode property of the
        // application's PhoneApplicationService object to Disabled.
        // Caution:- Use this under debug mode only. 
        // Application that disables user idle detection will continue to run
        // and consume battery power when the user is not using the phone.
        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).

Windows Phone Emulator setting in the debug options.

When the emulator is firing up, it looks like this:

Windows Phone Emulator loading

Once the application has loaded, it looks like this:

The application loaded up.

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.

Graphics Performance Bar

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:

  1. 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).
  2. 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.
  3. The texture memory usage. This tells us how much video memory is being used to store application textures.
  4. The surface counter. This shows the number of surfaces being passed to the graphics chip.
  5. The total number of intermediate textures used.
  6. 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.

    // Code to execute when the application is launching (eg, from Start)
    // This code will not execute when the application is reactivated
    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
    }

    // Code to execute when the application is activated (brought to foreground)
    // This code will not execute when the application is first launched
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
    }

    // Code to execute when the application is deactivated (sent to background)
    // This code will not execute when the application is closing
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
    }

    // Code to execute when the application is closing (eg, user hit Back)
    // This code will not execute when the application is deactivated
    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)
      {
        // A navigation has failed; break into the debugger
        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)
      {
        // An unhandled exception has occurred; break into the debugger
        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

    // Avoid double-initialization
    private bool phoneApplicationInitialized = false;

    // Do not add any additional code to this method
    private void InitializePhoneApplication()
    {
      if (phoneApplicationInitialized)
        return;

      // Create the frame but don't set it as RootVisual yet; this allows the splash
      // screen to remain active until the application is ready to render.
      RootFrame = new PhoneApplicationFrame();
      RootFrame.Navigated += CompleteInitializePhoneApplication;

      // Handle navigation failures
      RootFrame.NavigationFailed += RootFrame_NavigationFailed;

      // Ensure we don't initialize again
      phoneApplicationInitialized = true;
    }

    // Do not add any additional code to this method
    private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
    {
      // Set the root visual to allow the application to render
      if (RootVisual != RootFrame)
        RootVisual = RootFrame;

      // Remove this handler since it is no longer needed
      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">

  <!--LayoutRoot is the root grid where all page content is placed-->
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <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>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
  </Grid>

  <!--Sample code showing usage of ApplicationBar-->
  <!--<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
      <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
      <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
      <shell:ApplicationBar.MenuItems>
        <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
        <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
      </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
  </phone:PhoneApplicationPage.ApplicationBar>-->

</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:

   <!--LayoutRoot is the root grid where all page content is placed-->
  <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>

    <!--TitlePanel contains the name of the application and page title-->
    <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>

    <!--ContentPanel - place additional content here-->
    <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:

  1. 101 Windows Phone 7 Apps, Volume I by Adam Nathan[^]
  2. Professional Windows Phone 7 Application Development: Building Applications and Games Using Visual Studio, Silverlight, and XNA by Nick Randolph and Christopher Fairbairn[^]
  3. Microsoft Silverlight Edition: Programming Windows Phone 7 by Charles Petzold[^]
  4. Pro Windows Phone 7 Development by Rob Cameron[^]
  5. 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
QuestionMy vote of 5 PinmemberAlirezaDehqani27-Oct-12 9:12 
GeneralMy vote of 5 PinmemberAditya_Pandey21-Sep-12 18:01 
GeneralMy vote of 5 PinmemberFarhan Ghumra27-Jun-12 22:51 
QuestionWow... Excellent work. [modified] Pinmemberkartalyildirim4-Mar-12 0:39 
GeneralMy vote of 5 PinmemberMartin Hart Turner23-Jan-12 4:03 
QuestionPlease sir, can I have some more? PinmentorDaveyM699-Jan-12 4:20 
AnswerRe: Please sir, can I have some more? PinprotectorPete O'Hanlon9-Jan-12 6:17 
GeneralRe: Please sir, can I have some more? PinmentorDaveyM699-Jan-12 7:27 
GeneralRe: Please sir, can I have some more? PinprotectorPete O'Hanlon9-Jan-12 21:49 
GeneralRe: Please sir, can I have some more? PinmentorDaveyM699-Jan-12 23:09 
GeneralRe: Please sir, can I have some more? PinprotectorPete O'Hanlon9-Jan-12 23:55 
QuestionNice PinmemberMember 456543323-Sep-11 22:54 
GeneralMy vote of 5 PingroupSaraf Talukder6-Sep-11 10:11 
QuestionSo let me get this straight, your article has one button and you get best article for july. Pinmemberrj4522-Aug-11 11:40 
AnswerRe: So let me get this straight, your article has one button and you get best article for july. PinprotectorPete O'Hanlon27-Aug-11 10:01 
GeneralMy vote of 5 PinmemberThatsAlok10-Aug-11 19:53 
GeneralRe: My vote of 5 PinprotectorPete O'Hanlon14-Aug-11 8:09 
QuestionPhones you say, I like IPhones PinmvpSacha Barber8-Aug-11 5:18 
GeneralGreat job +5! PinmemberS Houghtelin20-Jul-11 9:20 
GeneralRe: Great job +5! PinprotectorPete O'Hanlon20-Jul-11 11:33 
GeneralMy vote of 5 PinmemberTarun K.S19-Jul-11 20:08 
GeneralRe: My vote of 5 PinprotectorPete O'Hanlon19-Jul-11 21:14 
QuestionAny experience with fast reflection in WP7? PinmemberMehdi Gholam18-Jul-11 22:04 
AnswerRe: Any experience with fast reflection in WP7? PinprotectorPete O'Hanlon18-Jul-11 23:44 
GeneralRe: Any experience with fast reflection in WP7? PinmemberMehdi Gholam18-Jul-11 23:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 14 Jul 2011
Article Copyright 2011 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid