Part 21 - Exercise: I Love Cupcakes App
Download the source code for this lesson at http://absolutebeginner.codeplex.com/
In this exercise, I want to build an entire app based on the lessons we have learned about the Hub App project template. I want to show you how easy it is to transform that default Hub App project template into something completely different. In this case we will create a media application that will display images and recipes of cupcakes as well as instructional videos of how to make cupcakes.
Start by creating a new Project. In the New Project dialog, (1) select the Hub App template, (2) rename to: ILoveCupcakes, (3) Click OK:
First, we’ll remove all of the assets in order to replace them with our own tiles, backgrounds, etc. In the Assets folder, select all files:
… then use the Delete keyboard key. When asked to confirm, select OK:
Lesson21.zip contains an Assets folder with all of the images for app tiles, hub images, background images, etc. In Windows Explorer, (1) select everything EXCEPT SampleData.json, and (2) right-click and select Copy from the context menu.
Right-click the Assets folder in the Solution Explorer and select Paste. Your file structure should look similar to this:
Next, (1) open the package.appxmanifest, and (2) in the Application tab, modify the Display name property to: I Love Cupcakes …
Next, (1) select the Visual Assets tab, (2) select the Square 71x71 Logo, (3) select the ellipsis button beneath the Scaled 240 asset …
… in the Select Image dialog, (1) select the ILoveCupcakes-170.png, and (2) click Open.
Repeat that technique to select the proper scaled image for (1) the Square 150x150 Logo, (2) the Wide 310x150 Logo, (3) the Square 44x44 Logo, (4) the Splash Screen, each time (5) selecting the appropriate image from the Assets folder.
(1) Select the Square 71x71 Logo page again, and this time (2) in the show name check boxes, place a check next to both check boxes.
If you open the HubPage.xaml, you’ll see that the background image is no longer visible. In fact, the background is transparent. This is because the style used for the background is no longer referencing an image in our project. We’ll fix that in a moment.
First, on the HubPage.xaml we’ll want to remove the Hub Sections we no longer need. I’ll comment out the definition for HubSection1 …
… as well as HubSection4 and HubSection5:
Next, I’ll locate the parent Hub control. Notice that the Background property for the control is bound to a ThemeResource called HubBackgroundImageBrush. I’ll place my mouse cursor inside of that identifier and select the F12 key on my keyboard:
… to view the definition for that ThemeResource. The ImageSource property of the ImageBrush is set to an image that no longer exists in our project:
I’ll update the reference to the new background image called: ilovecupcakes-background.png …
Now, when I return to the HubPage.xaml, I can see the pink background. Furthermore, I’ll modify the Header property of the HubSection1 to “RECIPES” and see it reflected in the preview pane:
Likewise, I’ll update HubSection3’s Header to “VIDEOS” and see that change in the preview pane as well:
At this point, we’ve make significant changes to the app (although we haven’t re-written much code per se). Most of the changes have been “configuration” changes up to now.
The app is styled as we would expect. However, we’re missing data. We’ll fix that soon.
If you select the Windows button and navigate to the Apps page, you can see the app’s icon and title appears as we would expect:
Furthermore, if we pin the app to the Start page and modify the tile sizes, we can see the the titles appear …
... And the large branded tile appears as well:
Now it’s time to make more significant changes to the app, specifically the data model. In the SampleDataSource.cs, we’ll modify the SampleDataItem class adding a property called Type. We’ll use the Type property to determine whether to navigate to a page that can display recipes and images or a page that can display video.
I’ll use the prop [tab] [tab] code snippet to create the new Type property of type string:
I’ll also change the constructor to allow the new type property to be passed in at construction, and will set the property in the same manner as the other properties are set:
The other change comes when we’re loading the JSON into memory. Therefore, we have to update the creation of new SampleDataItems in the GetSampleDataAsync() to include the new input parameter to the constructor:
(1) Open the the SampleData.json file. (2) Currently doesn’t have a “Type” property. Furthermore, there’s a lot of data to input including Group and Item titles, subtitles, image paths, etc. To keep this lesson short and reduce the possibility of fat-fingering the data in the file (causing runtime errors), I decided to create an alternative SampleData.json that we’ll copy into our project. Before we delete this file, take note that (3) the Build Action property of the file is set to “Content”. When I replace this file, I’ll need to make sure to set that property correctly to ensure the compilation process treats our new SampleData.json correctly.
First, I’ll delete the current SampleData.json. In Windows Explorer, in Lesson21.zip’s Assets folder, drag and drop the new SampleData.json into the DataModel folder of the project in the Solution Explorer.
(1) Select the new SampleData.json file in the Solution Explorer, then (2) in the Build Action, change the value from None (the default) to (3) Content.
If you open the new SampleData.json, you can see the shape of the data has changed to reflect our new Type property and the data also is specific to our app.
If we re-run the app, we should now see images and cupcake-specific titles for the tiles in the Hub control.
The next step is to set up the navigation from these tiles in the Hub control to pages that can display the pictures and recipe data or the “How To” videos for making cupcakes. For the former requirement, I’ll simply re-use the ItemPage.xaml. For the latter, I’ll add a new video.xaml page.
Right-click the project name in the Solution Explorer, select Add > New Item … from the context menu. In the Add New Item dialog, (1) select Basic Page, (2) change the name to Video.xaml, (3) click the Add button:
In the new Video.xaml page, I’ll add a MediaElement control telling it to stretch to the dimensions of the parent grid, and setting the AutoPlay property to true, play as soon as the media source is determined:
In the Video.xaml.cs, we need to determine which video to load into the MediaElement. To do this, we’ll need to accept a parameter from the HubPage.xaml. We’ll use the UniqueID of the SampleDataItem to determine which video should be displayed. The UniqueID should be the same as the name of the video, sans the file extension “.mp4”. Therefore, when a user taps a thumbnail image on HubSection3, we’ll determine the UniqueID associated with that item, and pass that UniqueID as a navigation parameter to the Video.xaml page. In the NavigationHelper_LoadState() method, we’ll retrieve the SampleDataItem associated with the UniqueID (via the LoadStateEventArgs.NavigationParameter), we’ll construct a URI to the video file in the Assets folder by appending the file extension “.mp4” to the UniqueID. Finally, we’ll set the MediaElement’s Source property to the newly constructed URI.
There are a few problems with this code that need to be resolved. First, we need to add a using statement for the ILoveCupcakes.Data namespace. Second, we’ll need to add the async keyword to the method signature to accommodate the await keyword when calling SampleDataSource.GetItemAsync.
Also, if we want to set the title of the page, we’ll need to give the TextBlock that contains the page title a name.
Therefore, back in Video.xaml, I’ll modify the page title in the “TitlePanel” by giving it a programmatic name “PageTitle” so that our C# code that sets it will work:
That concludes the changes required to the Video.xaml.
Next, we’ll need to modify the ItemPage.xaml which will display the app’s title, and we’ll add a StackPanel in the Grid named “ContentRoot” to display an Image and a TextBlock. After adding the XAML (below) you can see the changes to the ItemPage.xaml’s preview:
Since the ItemPage.xaml was already “wired up” by the project template, no further changes will be necessary.
The last significant change will be in the logic that determines whether to send the user to the ItemPage.xaml or the Video.xaml page based on the type of the item in the Hub’s ItemView controls that the user clicked on. Note that both ItemView controls (defined in HubSection2 and HubSection3) use the same event handler method, ItemView_ItemClick. Therefore, we’ll retrieve the ItemClickEventArgs.ClickedItem input parameter which lets us know which item was clicked and cast it to SampleDataItem. Once we have the item, we can determine both the Type and UniqueID properties for the selected item.
If the Type is “Recipe”, then we’ll send the user to the ItemPage. If the Type is “Video”, we’ll send them to the Video.xaml page. In both cases, we’ll send the UniqueID so that the proper SampleDataItem is displayed to the user.
One final issue remains. While we attempted to change the app name in several places in our XAML, it seems to ignore those changes. The answer is that these settings were localized. Localization is a topic we don’t cover in this series, however it allows you to create mutli-language versions of your app based on the user’s language and region preferences. In this case, we’ll open the Strings\en-US\Resources.resw file in the Solution Explorer and modify the top two properties setting their values to “i love cupcakes”.
Furthermore, in the Video.xaml page, I’ll make sure to update the title of the app (since I forgot to do it earlier):
Now, when I run the app, it looks complete and the app’s name is consistent throughout.
I see one last tweak to the default layout of the ItemTemplate for my videos … there’s no space between each of the video thumbnail images.
To fix this, I’ll return to HubSection3 and locate the ListView’s ItemTemplate property. It is set to a page resource called StandardTripleLineItemTemplate. I’ll put my mouse cursor on that name and press the F12 key on my keyboard to find its definition near the top of the page.
In the DataTemplate called StandardTripleLineItemTemplate, I’ll add a Margin=”0,0,0,20” to put 20 pixels of space below each item.
There are many other small tweaks we could make to the styling and layout, but we’ll consider this exercise complete.