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


WPF Meets the iPhone : Page 5

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

Creating the Main Button Panel
Next, you will create the main panel that contains the iPhone application buttons. To do this, go to Expression Blend's Objects and Timeline palette and double-click grdMainPanel. In the Asset Library, drag a Grid element and drop it in the row directly below the grdStatusPanel. To position the Grid, select the Direct Selection arrow from the Toolbox then drag the Grid to the upper left corner of the row until the red dotted lines appear to its top and left.

Next, in the Toolbox select the Selection arrow (first in the list) and resize the Grid until it fills Row 2 as indicated by the appearance of the red dotted lines to the right and bottom (see Figure 15). If you have positioned the Grid correctly, its Row property should be set to 2 and all Margin settings should be zero (0). In the Property palette, change the name of the Grid to grdMainButtonPanel to make it easier to identify.

Figure 15. Positioning a Grid: The red dotted lines in Blend allow you to position elements at the very top and left of a container.
Figure 16. Default Grid Spacing: By default, the height and width of Grid columns and rows are evenly divided between the available space.
Now you need to add columns and rows to the grid to accommodate the iPhone application buttons. To do this, go to the Properties palette, click the Properties button and under Layout extended properties, click the RowDefinitions property's ellipses button. In the RowDefinition Collection Editor, click "Add another item" four times to add four rows to the Grid, and then click OK. Next, go to the Property palette and click the ColumnDefinitions property's ellipses button. In the ColumnDefinition Collection Editor, click the "Add another item" button four times to add four columns to the Grid, and then close the editor. To see the newly added rows and columns as shown in Figure 16, go to the Objects and Timeline palette and double-click grdMainButtonPanel.

Creating an iPhone Button User Control
Now you'll create the iPhone application buttons. As you can see in Figure 1, an iPhone button contains both an image and associated text. In addition, there is no visible button border as is usual with WPF buttons, meaning you'll have to create a custom button control to imitate this look. All WPF controls are "lookless" in that you can change everything about their appearance while maintaining their behavior. You can use this feature when recreating the iPhone application buttons. Because you need to create multiple iPhone application buttons (one for each application) it make sense to create a reusable user control that contains an image and a label but allows you to specify the displayed image and label text.

To start, go to the Projects palette, right-click the project (the second node in the list) and select "Add New Item…" from the shortcut menu. In the Add New Item dialog, select UserControl, and change the name of the control to iPhoneButton.xaml. Make sure you've selected the "Include code file" checkbox, and then click OK to create the new user control.

Next, in the Objects and Timeline palette, select the UserControl item, then go to the Properties palette, and under Layout set the Width to 50 and the Height to 75. Although it may seem that you are hard-coding the control's size, you aren't—you are simply setting its default size when you drop it on a design surface.

Figure 17. Editing Templates: Expression Blend has a template editing feature that allows you to select an existing user interface element and create a new control template from it.
Now you need to add a standard WPF button to the User Control. To do this, go to the Asset Library, select a Button, and drop it in the User Control. Afterwards, go to the Properties palette and set all Margin values to zero (0). Next, right-click the Button and select Edit Control Parts (Template) → Edit a Copy… from the shortcut menu. That launches the Create Style Resource dialog box. Set the Name (Key) value to NoChromeButton, set the "Define in" option to Application and then click OK to save. This puts you into template editing mode as shown in Figure 17.

The Objects and Timeline palette now displays the sub-elements that comprise a Button—in this case, a ContentContainer and ContentPresenter. Because you need to provide a completely different look for the iPhone button, right-click the ContentContainer in the Objects and Timeline palette, and select Delete from the shortcut menu. This completely removes all visual aspects of the Button. However, in order for this custom Button to display custom content, you need to add a ContentPresenter element back into the Button. To do this, go to the Asset Library, select Content Presenter, and then double-click the ContentPresenter in the most-recently-used list. You are finished editing the control template, so click the up arrow at the top of the Objects and Timeline palette (it has a Return Scope to UserControl tool tip) which takes you out of template editing mode.

You can now see the Button outline in the upper left corner of the user control. To make it fill the entire user control, go the Properties palette, and reset the HorizontalAlignment and VerticalAlignment properties. To do this, click the tiny square to the right of these properties (they have the "Advanced Property Options" tool tip) and select Reset from the popup.

Now it's time to add an Image and Label inside the button to give it a visual appearance. First, add a Grid to the button that allows you to position these elements. Go the Objects and Timeline palette and double-click Button to select it as the active container. Next, go to the Asset Library, select Grid, and drop it in the Button. With the Grid selected, go to the Properties palette, and under "Layout extended properties," click the ellipses button next to the RowDefinitions property. Add two Rows to the Grid by clicking "Add another item" twice. Before exiting the dialog box, select Row 0 and set its Height property to .75*. Next, select Row 1 and set is Height property to .25*. This allocates 75 percent of the Grid height to Row 0 and 25 percent to Row 1. Click OK.

To see the new Rows, go to Objects and Timeline and double-click Grid. Now go to the Asset Library, select Image, and drop it in Row 0 of the Grid. Reposition the image so it is in the upper left corner of Row 0, and then resize it so it fills the Row. If you have done this correctly, the Image should have a Row property value of zero (0), RowSpan of one (1), and all Margin values should be zero (0). Now set the Width and Height of the Image to 50. Next, go to the Asset Library, select a Label, and then drop it in Row 1 of the Grid. Rather than manually positioning and resizing the label, go to the Properties palette and make sure its Row property is set to one (1), HorizontalAlignment to Center, VerticalAlignment to Bottom, and all Margin values to zero (0).

You can't see the text of the label because by default, its Foreground color is black. You have already created a style resource for text, so let's use it on the Button's Label. To do this, make sure you've selected the Label, and then go to the Properties palette. Under the Brushes category select the Foreground property. Select the "Color resources" tab and then select the TextForeground style you created earlier in this article. The text of the Label should now be white—but notice it is only partially displayed. To fix this problem, in the Property palette's Layout category change all Padding settings to zero (0).

Next, to give a little breathing room around the Image at the top of the button and the Label at the bottom, select the Grid in the Objects and Timeline palette, go to the Properties palette, and in the Margin property set both the top margin (the arrow pointing up) and the bottom margin (the arrow pointing down) to five (5).

Using Dependency Properties
At this point the iPhoneButton user control contains an Image and Label. However, if you drop one of these controls on a WPF design surface, you cannot set the Image's Source property to specify the image or set the Label's Text property to specify the display text. Why? Because you cannot access user interface elements contained inside a user control.

To get around this problem, you can add properties to the outer user control container and use them to set the image and text indirectly. However, rather than adding regular .NET properties, it's best to add dependency properties instead. A dependency property is a special kind of property that has additional behavior that you can use in this scenario. It features the ability to data bind to the dependency property. You can easily data bind the contained Image's Source property to a custom ImageSource dependency property defined on the parent user control, and data bind the contained Label's Text property to a custom LabelText dependency property.

To do this, go to the Project palette and expand the iPhoneButton.xaml file by clicking the arrow to its left. Afterward, double-click its associated iPhoneButton.xaml.cs/vb file to open it in Visual Studio. At the top of the source code file, add the following statement to import the specified namespace.

   // in C#:
   using System.ComponentModel;
   ' in Visual Basic:
   Imports System.ComponentModel
Next, if using C# add the code in Listing 3 to the class definition, and if using VB use the code in Listing 4. Notice this code contains the definition of two dependency properties named LabelContentProperty and ImageSourceProperty. They have two associated properties, LabelContent and ImageSource, which are standard .NET properties that act as wrappers for the dependency properties. This allows you to use the dependency properties just as you normally use regular .NET properties. Press Ctrl+Shift+S to save all changes.

Figure 18. Create Data Binding Dialog: You can use Expression Blend's Create Data Binding dialog to bind to a data field, an element property or an explicit data context.
Now go back to Expression Blend and press Ctrl+Shift+B to compile the code you just added in Visual Studio. Next, select the Image element in the Objects and Timeline palette, and then go to the Properties palette. Under the Common Properties category, locate the Source property. Click the tiny square to the right of the property (its tool tip says Advanced Property Options) and select "Data Binding…" from the popup. This launches the Create Data Binding dialog box. Because you need to bind to the user control's dependency property, select the Element Property tab as shown in Figure 18. Afterward, in the left side of the tab under "Scene elements," select UserControl. Then on the right side of the dialog under Properties, select the ImageSource property. Click Finish to close the dialog box. Now the Source property of the contained Image is data bound to the ImageSource property of the user control. Notice there is an orange rectangle with rounded corners displayed around the ImageSource property in the Property palette. This indicates a data bound property.

Finally, to data bind the contained Label, go to the Objects and Timeline palette and select the Label. Go to the Properties palette, and under the Common Properties category find the Content property. Click the tiny square Advanced Properties box to its immediate right and select Data Binding from the popup. In the Create Data Binding dialog box, select the Element Property tab. On the left side under Scene elements make sure you've selected UserControl. Then on the right side under Properties, scroll down and select the LabelContent dependency property and click Finish. Now the Content property of the contained Label is data bound to the LabelContent property of the user control. Notice the Label text no longer appears in the design surface of the user control. This is because the Content property is no longer hard-coded to the string "Label."

Now you can add the iPhoneButton user control. To do this, first rebuild your project by pressing Ctrl+Shift+B or by selecting Build Solution from the Projects menu. Next, select the Projects palette and double-click iPhoneWindow.xaml to open it for editing. In the Objects and Timeline palette, double-click grdMainButtonPanel to select the Grid and display its columns and rows. Now go to the Asset Library and select the Custom Controls header. Select the iPhoneButton, drag it into Column 0 and Row 0 of grdMainPanel, and then reposition and resize it so it fills the entire cell. Next, go to the Properties palette and under Common Properties, locate the ImageSource and LabelContent properties (the dependency properties you created for the user control). They are listed under the Common Properties category because they were adorned with the Category("Custom Properties") attribute (as shown in Listing 3 and Listing 4). Expand the ImageSource property's combo box and select the Text.png image from the list. This should automatically display the image on the button. Notice the default value of the label's Content property has been set to Text. This is because the LabelContentProperty dependency property as declared in Listing 3 and Listing 4 has a default property value specified in this parameter:

Oddly enough, you actually want to leave the default value intact, because Text is the correct string in this case, indicating this button is used for text messaging. To finish up the SMS text button, go to the Properties palette, and under the Layout category, reset the Width and Height properties to Auto by clicking the button to their immediate right (it has the tool tip "Set to Auto"). Next, go to the HorizontalAlignment and VerticalAlignment properties and reset them to Stretch. Also, make sure you set all Margin values to zero (0). This should visually center the button in the upper left cell of the Grid.

The easiest way to add the other application buttons is to copy the Text Messaging button by pressing Ctrl+C and then Ctrl+V. This places the new copy of the button directly on top of the SMS Text button. Afterwards, just move it to the next column in the row, and then change its ImageSource and LabelText properties as shown in the following list (make sure each button's Margin values are set to zero (0) and its Row, Column, RowSpan and ColumnSpan properties are set properly):

  • Row 0: text.png | Text
  • Row 0: calendar.png | Calendar
  • Row 0: photos.png | Photos
  • Row 0: camera.png | Camera
  • Row 1: youtube.png | YouTube
  • Row 1: stocks.png | Stocks
  • Row 1: maps.png | Maps
  • Row 1: weather.png | Weather
  • Row 2: clock.png | Clock
  • Row 2: calculator.png | Calculator
  • Row 2: notes.png | Notes
  • Row 2: settings.png | Settings
When you're finished, your application button panel should look like the panel shown in Figure 1. At this point the buttons don't do anything, but if you want to see how it looks so far at run time, press F5 to compile and run the project.

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