WEBINAR:
On-Demand
Building the Right Environment to Support AI, Machine Learning and Deep Learning
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.