RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


WPF Meets the iPhone : Page 4

Find out how to add iPhone-like UI features to your WPF applications.

Creating the iPhone Status Bar
Now it's time to create the iPhone status bar that displays signal strength, carrier, current time, and battery charge level. In the downloadable code for this article you'll find a zip file that contains a number of graphics you can add to your project that will allow you to recreate the iPhone look and feel. To do this, unzip the file into your project's root directory which is C:\iPhone\iPhone (WPF projects are contained in a subfolder below the solution folder). Next, go to Visual Studio's Solution Explorer (not Expression Blend), select the iPhone project, and then click the "Show All Files" button at the top of the Properties palette. This displays all the files you just unzipped into your project's root folder.

Right-click the Images folder, and select "Include in Project" from the shortcut menu. This includes these files and folders in the project, as indicated by the change in their associated icons. Now go to the Visual Studio File menu and select Save All. Next, press Alt+Tab to go back to Expression Blend and click "Yes" in the dialog asking if you want to reload the project. This closes all open files and displays the newly added files and folders in the Project palette.

Double-click the iPhoneWindow.xaml file in the Project palette to reopen it. To create the status bar you need to add a child Grid to the second Row (Row 1) of grdMainPanel. To do this, double-click the Grid control in the most-recently-used list. This adds a new Grid to the top left corner of grdMainPanel. Go to the Properties palette and change the Name property of the newly added Grid to grdStatusPanel.

Next, go to Blend's Toolbox and select the Direct Selection tool (the white arrow second from the top). Click on the newly added grdStatusPanel and position it in the far left and top of the second row of grdMainPanel until you see red dotted lines displayed on the top and left of the Grid as shown in Figure 15. This indicates the Grid is positioned at the very top and left of grdMainPanel's second row. To resize the new Grid, go back to the Blend Toolbox and choose the Select tool, which is the dark arrow at the very top of the Toolbox. (Note that you can also press the letter A to toggle the selection pointer to Direct Selection and press the letter V to toggle to regular Selection.) Resize grdStatusPanel until you see a red dotted line on the far right and bottom of the Grid. If you have done this correctly, grdStatusPanel's Width and Height properties should be set to Auto, and all its Margin settings should be zero (0). In addition, its Row property should be set to one (1), indicating it is located in the second row of the parent Grid.

To position the different controls that you will be placing in the status bar, you need to add four columns to grdStatusPanel. To do this, go to the Properties window, find the ColumnDefinitions property located in the Layout category and click its associated ellipses button (to see this property you may need to click on the arrow at the bottom of the Layout category which displays advanced properties). This launches the ColumnDefinition Collection Editor dialog box. Click the "Add another item" button four times to add four columns to the Grid. Click OK to close the ColumnDefinition Collection Editor. Go to the Objects and Timeline palette and double-click grdStatusPanel to see the four new columns you have added.

Now it's time to add a signal image to the status bar. This is a static image rather than a true indicator of signal strength because there really is no cell phone signal strength to display. To add this image, go to the Project palette and expand the Images folder, then expand the Signal folder. Find the FSO_5_Bars.png image file, and then double-click it to add it to the first column of grdStatusPanel. If the image is positioned correctly, its Column property should be zero (0) and all its Margin settings should also be zero (0).

Next, go back to the Projects palette, and select the Images → Battery → FSO_BatteryCharged.png image. Drop it in the far right of the fourth column of grdStatusPanel. Reposition the image until you see a red dotted line on its right, top, and bottom.

Now you are ready to add two labels to the status panel. First, select the Label control from the Asset Library, drag it directly from the Asset library (rather than from the most-recently used list), and drop it in the second column of grdStatusPanel. Reposition the label so it is in the far left of the second column. By default, a label's text is black, so you won't see any text yet. To make the text visible, with the label selected, go to the Properties palette, select the Foreground property and change the R, G, and B values to 255, 255, 255. Again, rather than hard-coding this foreground color everywhere it's needed, it's best to create a style resource instead. As you did previously, click the double-headed arrow button next to the Hex Value text box to launch the Create Color Resource dialog box. Specify the Name (Key) as TextForeground, select the Application radio button to create an application-level resource, and then click OK to save it. At this point you may notice the label text is only partially displayed. To display all the text, go to the Properties palette and set the label's Padding property to 0, 0, 0, 0. Finally, change the label's Content property to AT&T.

Notice the label is displayed far to the right of the signal icon rather than right next to it as shown in Figure 1. This is because the Width property of all columns in grdStatusPanel is set to * (star), which specifies that each column width is divided evenly. This setting is easiest for laying out the status bar, but now you need to change it so you can position elements in the status bar properly. To do this, first select grdStatusPanel in the Objects and Timeline palette. Next, go to the Properties palette and edit the ColumnDefinitions property. In the Column Definition dialog box, set the Width property of columns 0, 1, and 3 (not 2) to Auto, which specifies the columns only take up the space needed for the elements they contain. Click OK. Notice the AT&T label is now butted right up against the signal icon without any space between. To fix this, select the label (using the Direct Selection arrow) then go to the Properties palette and change its Margin property so the left margin (the left arrow button) is 5.

The final item that needs to be added to the status bar is a label that displays the current time. Because you have already created a label that has many of the settings you need, select the AT&T label and press Ctrl+C, then Ctrl+V to make a copy of it. This places the new label on top of the old label. Without manually repositioning the label, go to the Properties palette and set the following properties on the new label:

  • Name: lblTime
  • Column: 0
  • ColumnSpan: 4
  • Margin: 0, 0, 0, 0
  • HorizontalAlignment: Center
  • Content: 12:00 AM
When you are finished, your status panel should look like the status panel shown in Figure 1.

Working with DispatcherTimer
If you run your iPhone project by pressing F5, you will see the status bar clock is always set to 12:00 AM. To make this clock functional you can enlist the help of WPF's DispatcherTimer class. Unlike the traditional .NET Timer class, DispatcherTimer runs on the same thread as the Dispatcher of the user interface so the UI can be updated when its Tick event fires.

Since the application needs to set the clock when the Window first loads, you need to create a handler for the Window's Loaded event. To do this, go to the Objects and Timeline palette and select the Window (the top-level element), then go to the Properties palette and select the Events (lightning bolt) button. Next, find the Loaded event and double-click its associated text box. This opens the iPhoneWindow.xaml.cs/vb file in Visual Studio. Before adding code to this method, import the following namespace by adding this line of code to the top of the code-behind file.

   // in C#:
   using System.Windows.Threading;
   ' in Visual Basic:
   Imports System.Windows.Threading
In addition to adding code to the new Window_Loaded event handler method, you need to add a new class-level variable named Timer and two additional methods named Timer_Tick() and SetClock(). C# developers should add the code shown in Listing 1 to their code-behind file. Similarly, VB developers should add the code in Listing 2.

The Window_Loaded method fires when the form first loads calls the SetClock() method, which in turn sets the initial value of the label to the current time. Next, it instantiates a DispatcherTimer, sets its Interval property to one minute, and registers a handler method with its Tick event that calls SetClock() once each minute.

Press F5 to run the project again and you will see the current time displayed in the label. If you wait one minute you will see the time automatically change.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date