DiscoverWindows Phone 8 Development for Absolute Beginners (Audio) - Channel 9
Windows Phone 8 Development for Absolute Beginners  (Audio) - Channel 9
Claim Ownership

Windows Phone 8 Development for Absolute Beginners (Audio) - Channel 9

Author: Microsoft

Subscribed: 0Played: 0
Share

Description

Bob Tabor (LearnVisualStudio.NET) and Clint Rutkas (Microsoft/Channel9) team up to deliver this 11+ hour Windows Phone 8 Development for Absolute Beginners series! Not only will you learn the absolute basics of installing and working with Visual Studio Express 2012 for Windows Phone and the Emulator, but you'll also learn XAML layout and events, how to utilize many of the Phone's built in features and additional open-source libraries. Best of all, this series will walk you through building two complete store-worthy apps. The first app you'll build is the SoundBoard app that allows you play pre-recorded sounds and record your own custom sounds. The second app you'll build is the AroundMe app which integrates the Phone's Map, GPS and Lock Screen capabilities with Flickr's API. For more Absolute Beginner series visit: https://channel9.msdn.com/posts/Beginner Source Code: http://aka.ms/absbeginnerdevwp8 PDF Version: http://aka.ms/absbeginnerdevwp8pdf
35 Episodes
Reverse
Congratulations, you made it to the end of another video series. That's no small task—it took a lot of commitment to do that, not to mention time and attention, but hopefully you enjoyed the series and were compiling ideas for building your own apps and gaining confidence—not to mention the knowledge of the API, the techniques for working in the Visual Studio IDE and the Phone Emulator, and so on.Moving forward, I recommend a few things ...Stay on top of updates with the Windows Phone blog: http://blogs.windows.com/windows_phone/b/windowsphone/   ... I just realized I hadn't been there in a few days and there was a great promotion that I'm going to take advantage of when I finish recording this video. It contains the news and updates you'll want to know about straight from Microsoft.Also, the great WPCentral site: http://www.wpcentral.com/  ... will keep you abreast of new devices and apps that come out for the platform. Also, more pertinent to this series, the Windows Phone Developer blog: http://blogs.windows.com/windows_phone/b/wpdev/ To continue your learning, check this out: What's new in Windows Phone SDK 8.0https://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206940(v=vs.105).aspx  It gives a great overview of many of the new and advanced features. If you haven't already, you'll want to get a Phone Developer Center Membership. It will take a while for verification through Symantec, even longer if you're like me and have a tiny business with no history with Dun & Bradstreet or a phone number you want made public. If you haven't done so already, you'll want to get a Windows Phone 8 device. I highly recommend the Lumia 920 ... I've been using mine for about a month. And I'm just an individual here—I don't speak on behalf of Microsoft when I say that I'm no stranger to the devices of other manufacturers and platforms of other companies—but this phone and the ecosystem around it, including the apps, the Surface, and my new over-powered Windows 8 computer have been a blast. I love pinning tiles and seeing them update with new information. I love the built-in Skydrive support, especially in OneNote and Office for the Windows Phone 8. And the camera is awesome.  And I've never owned a Nokia product before, but I'm really impressed with the phone itself and, moreover, with the dedication to the Windows Phone 8 platform. So, my last recommendation is the dvlup.com program at Nokia.  http://www.dvlup.com  They are incentivizing developers to create apps and register them on the site to win prizes through a currency called DVLUP Reward Points. You can trade them in to get free phones, advertisements, or special placement in the store. They also have challenges ... at this moment, they have 42 challenges running. Complete the challenge and depending on the complexity of the challenge you earn points. I want to sincerely thank Randy Arnold, who is a Nokia Developer Ambassador in my area, for taking me under his wing and explaining Nokia's strategy, showing me how DVLUP works and why it's a great opportunity for developers as well as how it supports the Windows Phone 8 platform.I want to thank Larry Lieberman and Desiree Lockwood for their support in getting me the assets I needed for this series.As always, thanks to Golnaz and Dan Fernandez because they're always awesome.And most of all, thanks to Clint Rutkas who is "the man". Not only did he do most of the heavy lifting up front by building these great apps, which we had the pleasure of learning from, he also patiently answered over a hundred emails from me asking for help and guidance as I was learning the new features of the Windows Phone 8 as well as his approach and thought process as he set out to build these apps. It was a valuable learning experience for me, and hopefully for you, too.If you like what we did here and want more like it, make sure you let Channel 9 and Microsoft know. They will get you the resources you want.And if you liked this series, there's plenty more where this came from. Please take 3 minutes to check out my website:http://www.LearnVisualStudio.NET ... where I have tons of video training just like this on a wide variety of .NET topics.Finally, thank you for your kind attention and as we part ways I sincerely wish you the best. Let me know what you've built—I'd love to check it out. If I can ever help, email me at: bob@learnvisualstudio.netThank you.Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdf
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfAt this point, our AroundMe app is missing just one final feature: the ability to randomly change the lock screen to one of the pictures we've selected every few moments, even if the AroundMe app isn't currently running.This functionality requires we use a Scheduled Task Agent. The Scheduled Task Agent runs in the background and executes at specific intervals even when our program is not in the foreground -- in other words, when it is not the app you're working with on screen. In our case, we'll schedule the task to run every 30 seconds. When the scheduled task executes, it will call into our LockScreenHelper class' SetRandomImageFromLocalStorage() method.To enable this functionality we will add a new Windows Phone Scheduled Task Agent project to our current solution. This poses a problem ... we will need to execute the code in our LockscreenHelper.cs from our new project. However, currently this file (as well as its dependencies, the FlickrImages.cs and Photo.cs class files) reside in our main project at the moment. We could merely cut, copy and paste the code files so that they reside in both projects, however the better solution (from a code maintenance perspective) would be to create a third project, a Windows Phone Class Library project, that will house the shared code files, then reference it from both projects. We typically want to share code rather than duplicate it so that any changes or updates can be made in one place and shared by all dependents.Our game plan:We'll add a new Windows Phone Scheduled Task Agent project to our Solution We'll add a couple lines of code that will call the SetRandomImageFromLocalStorage() method and allow us to test it in the emulator We'll add a new Windows Phone Class Library project in our solution and will move our three class files into it that will be shared between the other two projects. We'll move those code files into the Windows Phone Class Library, we'll use NuGet to add in Newtonsoft's JSON library and the Microsoft.Net.Http library package, we'll clean up the namespaces and so on. We'll create references from the AroundMe project and the Scheduled Task Agent project to our new Class Library project. In the main AroundMe project, I'll need to introduce the Scheduled Task Agent to the operating system by launching it when AroundMe starts up, and configure the WMAppManifest.xml to be an extension in order to allow our app to be a Lock screen Background Provider. And if all goes well, we'll run it and watch the fireworks. I'm not going to submit this app to the store ... we've already seen that process in lesson 23, but I will show you some last steps required before submitting the app to the store, including how to get a token to properly license and use Map Services in your Phone Store app.  1. Add a new Windows Phone Scheduled Task Agent project to our solution called AroundMe.SchedulerI don't believe I've ever demonstrated how to add a second project to a solution in the C# Fundamentals series. Assuming you do not know how to do this ... Right-click the solution name in the Solution Explorer Select Add New Project ... The Add New Project dialog appears: Select the Visual C# Windows Phone templates Select Windows Phone Scheduled Task Agent project template Name it: AroundMe.Scheduler ... we'll use a common notation when naming projects, the dot notation, to match what we want the default namespace for our code in this project to have Click OK You should now see a second project in the Solution Explorer. The most important part of this project is the ScheduledAgent.cs class.  Most of code in the ScheduledAgent.cs file is "boiler plate" meaning we will not need to change it, but it must be there in order to create a valid Scheduled Task Agent. However, if you scroll down near the bottom of the file, in line 41 you'll find the OnInvoke() method with a TODO comment. This is where we'll implement our code as follows:  As you can see, I added a TODO. We'll come back here later and add code that will set the random image from local storage. We have a little setup work to do first.Before we do that, I've added one line of code (with about 10 lines of comments) that explain it's purpose. I copied it from this source:https://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.scheduler.scheduledactionservice.launchfortest(v=vs.105).aspxSo, line 61 of the code snippet above:ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(30));... is merely for testing purposes in the Phone Emulator. This allows developers to watch the behavior of the task every 30 seconds. Otherwise, as we'll learn in a moment, when our app is deployed to a real Phone device, it will only run once every 20 to 40 minutes. More about that in just a moment.As the comments above it explain, we need to either remove this line of code, or at least wrap it in an if statement like this:if (Debugger.IsAttached) { }The original article references this additional background information:https://msdn.microsoft.com/en-US/library/windowsphone/develop/hh202942(v=vs.105).aspxThat article is very important for our purposes, and if you think you need to do some background processing or scheduled processing, you MUST read that article. In a nutshell, there are two types of background tasks: ResourceIntensiveTasks and PeriodicTasks. Resource Intensive tasks run in the background because they may take a long time to complete ... they're processor intensive. PeriodicTasks run at set intervals. In our case, we're creating a PeriodicTask.There are different rules and constraints depending on the type of background task we're working with. Both ResourceIntensiveTasks and PeriodicTasks share the following constraints:An application may have only one background agent, and only one instance of the agent runs at a time. We're limited by which of the Phone's APIs we can utilize from a background task We're limited by the amount of the phone's resources we can use ... no more than 11 megabytes for an application like ours Our scheduled task will only work for two weeks before it needs to be rescheduled by re-running the AroundMe app If our app crashes twice in a row, it will be unscheduled by the operating systemIn our case, since we're working with PeriodicTasks, we need to be aware of a few additional things: Our task will run about every 30 minutes, however the phone's operating system decides when to run the tasks. In fact, it might run ALL scheduled tasks at the same time because it's more efficient to use the phone's battery once every 30 minutes than a bunch of times during that same period for each individual Scheduled Task that wants to run. So, that 30 minute time frame can drift as much as 10 minutes in either direction. So, when we deploy our AroundMe app to a phone, it will change image every 20 to 40 minutes or so. Our Scheduled task can only run for 25 seconds before it is shut down by the operating system. That shouldn't affect us, but we should be aware of that for future reference. If the battery is low and the phone goes into Battery Saver mode, then our Scheduled Task may not run at all. If you have a Windows Phone 8 and your batter gets low, you'll see a little heart icon over the battery meaning that it has shut down scheduled tasks, turned off some of the functionality of the phone like the GPS and Bluetooth radio and more. Users can configure how aggressive they want Battery Saver to be in the Settings screen. I have a battery monitoring app on my start page, and I was getting low on battery, then I noticed that Battery Saver mode kicked in and I had 20 hours left. That's because it was throttling what was going on in the background. So, be aware of that when you create your own Scheduled Tasks. Finally, depending on each phone's configuration, there may be a limit to how many background agents can run at the same time. A few days ago I hit that limit and it asked me to choose some background tasks to shut down because the phone was low on memory. So, if you plan on submitting a phone to the Store you'll need to be willing to support users. If you want to support your users, you'll need to know a little about how the phone and the operating system work with your app. If the user complains that their background is not changing often enough, you might want to ask a few questions about how many apps are currently running.To see what's running in the background, go to your Windows Phone's settings, swipe over to the applications page. There you will find "background tasks" setting at the top of the list. Once inside the settings, you'll see a list of all the apps running in the background. To shut it down, just tap on the app and tap the "block" button. To confirm that you've shut down the app, press and hold the back button to view any open apps.At any rate, that article also does a nice job of explaining the general lifecycle of a background agents. From the article:"When the agent is launched, the operating system calls OnInvoke(ScheduledTask) ... When the agent has completed its task, it should call NotifyComplete() or Abort() to let the operating system know that it has completed. NotifyComplete should be used if the task was successful. If the agent is unable to perform its task – such as a needed server being unavailable - the agent should call Abort, which causes the IsScheduled property to be set to false."So that is the purpose of the NotifyComplete() in line 63 of the code snippet above.Again, we'll come back and revisit the TODO comment in line 45 after we've moved our class files from our main AroundMe project to a new Windows Phone Class Library project, which we'll do next. 2. Create a new Phone Class Library called AroundMe.Core and move class files to itJust like in step 1, we'll add a new project to our solution. So, right-click the our solution entry in the Solut
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfOur app is coming together nicely, but there's one last feature we want to implement. When the user selects one or more Flickr images in the LongListMultiSelector, we'll take the FlickrImage data and serialize it to disk using JSON. In this first pass, we'll randomly select one of those FlickrImage instances as the lock screen image once. Then in the next lesson, we'll randomly select from that list of serialized FlickrImages once every 30 minutes, which is ultimately our goal.So, our game plan in this lesson:Add an App Bar to the SearchResults.xaml page When at least one item is selected from our LongListMultiSelector, we'll show our app bar, otherwise we'll hide it We'll handle the click event for the new Set App Bar button, getting a list of selected Flickr images We'll add a new LockScreenHelpers.cs class and add functionality to: (a ) clean out any images that were already in local storage, (b ) save the new list of images into local storage, and (c ) select a random image and make it the phone's lock screen image. This is a very code-intensive lesson. For the most part, I'll provide an overview of several lines of code at a time. In some cases, I'll dive deeper to explain an individual class or method. However, if I ever skip something or if I don't explain it to your satisfaction, Microsoft's documentation is always the definitive source you should be referencing. You can't become a serious developer without consulting MSDN several times a day. 1. Add an App BarWe've done this several times already so I won't explain it in depth. I add the following method: In this code we simply create a new ApplicationBar() object (line 62) and create a single ApplicationBarIconButton (line 67) with a checkmark icon. On that button, we'll set the text (line 72) and wire up an event handler (line 73). Then we'll add the button to the ApplicationBar (line 75). Notice in line 63 that we set the IsVisible to false initially. We'll write display logic -- when one or more Flickr images are selected in our LongListMultiSelector, we'll make the ApplicationBar visible.Since we're creating a LOCALIZED ApplicationBar, and using AppResources in line 72 to set the button's text, we'll need to modify the AppResources.resx file located in the Resources folder of our project.  I add an AppBarSet entry and set it to the word "Set" ... this will be the text under our checkmark icon.Finally, we'll need to trigger our BuildLocalizedApplicationBar() method in the SearchResults.xaml.cs constructor like so: Now that we've created the Application Bar, we need to write the display logic to show it only when one or more Flickr images are selected.2. Write display logic in the SelectionChanged event handler of the LongListMultiSelectorWhen I first created the LongListSelector (prior to it becoming the LongListMultiSelector), I added a SelectionChanged event handler. I knew I would need it eventually. Now is that time.When the list of SELECTED items changes, we want to evaluate the number of items selected and show or hide the Application Bar accordingly.First, we need to add a Name attribute to the LongListMultiSelector so we can reference it programmatically in C#:Next, right-click line 49 (above):SelectionChanged="PhotosForLockscreen_SelectionChanged" >and select Navigate to Event Handler from the context menu. That will open the SearchResults.xaml.cs file again and allow us to add code to the PhotosForLockscreen_SelectionChanged event handler. We'll merely add a simple if else statement like so: Here we're checking the number of selected items in the PhotosForLockscreen LongListMultiSelector object and setting the visibility of the Application Bar accordingly.If we were to test our code, we should be able to select one item and see the Application Bar with the checkmark icon appear: ... and if we were to deselect that item, the Application Bar should disappear. 3. Write code to handle the Set Application Bar Button's Click eventWhen I wrote this line of code earlier in the BuildLocalizedApplicationBar() method:appBarButton.Click += appBarButton_Click;... Visual Studio created a stubbed out method called appBarButton_Click(). This is where we'll kick off much of the hard work in this application around saving the selected images and picking a random one to display on the lock screen, at least, initially.In the appBarButton_Click() method, I add the following code: After create a new generic List<FlickrImage>, I iterate through each selected item from the LongListMultiSelector and adding each one to the new List<FlickrImage> collection.In lines 91 through 93 I write a few comments ... these are TODOs ... I have more work to do prior to completing these steps. However, this list will drive the development of the three major features I'll implement in the remainder of this lesson. I'll implement them in a new helper class I'll create in a moment. I use the term "helper class" to talk about a class of related utility methods intended to interface with some part of the underlying system. Some may call this a facade ... it's a friendly face on top of, in this case, local or Isolated Storage and the Lock screen APIs.Finally, I'll notify the user that the operation completed successfully with a MessageBox. I want to see this in action so I can visualize how this will all work when it's doing what I have in my mind's eye. Perfect. That will be great ... but we have a lot of code to write to get this working correctly. 4. Add the LockScreenHelper.cs Class File and write the desired functionalityWe'll add a new item (Class) to the AroundMe project.In the Visual C# templates ... Make sure you create a Class file template And most importantly, name it: LockScreenHelpers.cs Click Add Recall from our gameplan for this lesson AND from the TODO list comments we added a moment ago that we'll need to enable three vital functionalities in this helper class:Clean out any images that were already in local storage, Save the new list of images into local storage, and ... Select a random image and make it the phone's lock screen image We'll start with the first task, deleting any existing files that may be around from previous AroundMe sessions. I write the following code: I have two methods: (1.) CleanStorage(), and a private method called (2.) TryToDeleteAllFiles() which is a helper function. Both of these are static meaning we will not have to create an instance of the LockScreenHelpers class. Helper classes and helper methods are usually static ... they don't need to maintain "state" per se ... we just need them to be a convenient container for our methods. We'll pass in the state (values) we need to operate on.CleanStorage() merely grabs a reference to the local storage for our app, and passes it to the TryToDeleteAllFiles() helper method, along with the sub folder we want to clean out. These two sub folder names / locations are stored as constants at the top of the class.The Images folder is something we will create in the next step to store copies of the images we selected from the LongListMultiSelector. The Shared/ShellContent folder is used for start page tiles, the app list icons and such.Back in the AppBarButton_Click() event handler, next we call the LockScreenHelpers.CleanStorage() method:  Next, we'll turn our attention to saving the list of selected images to IsolagedStorage. We'll implement another method in the LockScreenHelpers.cs file:  In the appBarButton_Click() event handler, we've already added the images selected in the LongListMultiSelector to a List<FlickrImage> called "imgs". We'll pass that collection in here because we want those images saved to IsolatedStorage. We'll convert (serialize) the List<FlickrImage> to Json for easy storage We'll get this app's IsolatedStorage area ... remember why we use the "using" statement? To properly release unmanaged resources like IsolatedStorage. We'll create a file and save the handle to it in a variable ... we'll use that handle to write to that new file in a moment. Handles to files involve unmanaged resource, so we utilize the using statement again here. Note the name of the file ... I'll create a constant string with the name in a moment. We employ a StreamWriter to write the Json into a new file. Back to callout #4 (above) ... I'll create a constant with the name of the file:  Back in the appBarButton_Click() event handler, we'll pass our List<FlickrImage> called imgs to our new LockScreenHelpers.SaveSelectedBackgroundScreens() method.  The next part is a bit more difficult. We want to choose an image from IsolatedStorage randomly to be the lock screen image. We'll tackle this in three parts:We'll open the Json file containing our List<FlickrImage> We'll randomly choose one of the items in that collection We'll call a helper method to actually do the dirty work of assigning that image as the new lock screen image   Since we've been reading and writing to IsolatedStorage quite a bit in this series, hopefully much of this code should look familiar, or at the very least, you should be able to figure out what's going on here. Lines 75 through 92 are opening up the Json file from IsolatedStorage and deserializing it back into a List<FlickrImage>. We do a check to make sure the Json file actually exists, and we open it and read it using a StreamReader. Assuming the List<FlickrImage> is not empty, we will choose a random number with an upper bounds set to the number of items in the List<FlickrImage> collection. If we have the debugger open while we're testing this, we will be able to see which image was chosen. We'll send the image to a helper method that will set it as the lock screen image ... we'll work on that next ...   Here, we want to isolate just the file name portion of the Uri. Uri.Segments splits up the Uri path into an array of strings containing the parts between the forward-slashes.  For more info
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfIn this lesson we'll refine our search results page by animating the images as they are loaded from Flickr. We want the images to ease in, fade in to view. We also want to provide feedback to the user of the app for long running operations like retrieving these photos over a slow internet connection by adding a progress indicator. And finally, I want to add some feedback in case the user searches their current location and topics and Flickr has no results to return ... we don't want to leave the user in the dark waiting for photos to appear that never come.So, our game plan in this lesson:We'll modify our LongListMultiSelector's DataTemplate -- we'll prepare the Image control for the fade in effect we'll implement We'll create an animation and storyboard targeting the image control to enable the fade in effect We'll make provisions for the possibility that there are no photos on Flickr that match our search criteria by creating and hiding a Text block that we'll un-hide when there are no photos to show We'll add a progress indicator that will run while we're performing the web service call to Flickr and loading the images  1. Prepare the Image control for a fade-in animationThe first step we'll take is to set the initial Opacity attribute of the Image to 0, indicating that we want to hide the contents of the image. 0 is completely transparent and 1 is completely opaque. 0.5 would be partially transparent / opaque.Then, for each image in our DataTemplate, as that particular image has downloaded from Flickr, the ImageOpened event will fire. We'll handle that event and write code to animate the change of the Opacity attribute.So, we'll make the following changes to the Image control: Add an Opacity attribute, set it to 0 Add an ImageOpened event handler attribute and wire it up to a new method called "Image_ImageOpenend", which we'll implement in the next step. Right-click anywhere on that line of code with the ImageOpened attribute or it's setting, select "Navigate to Event Handler" from the context menu. 2. Implement the Image_ImageOpened Event HandlerHere we'll write C# code to animate the fade in effect. Many examples of animation you'll see use XAML to define both the Storyboard and Animations associated with the storyboard, then use C# code to kick off the animation when a certain event is triggered. We could do it that way, but we've chosen to do it all with C# because we're dealing with a special situation (more about that in a moment).Animations are made up of a Storyboard object and at least one Animation object.Let's start with the Animation. First, there are several different types of animation data types. We're using a DoubleAnimation data type because we want to move a property from 0.0 to 1.0. There's also a ColorAnimation class for animating between two colors, and a PointAnimation for modifying an objects X Y coordinate or it's size.An Animation is basically a timeline combined with a result. The results are determined by the specific Animation class you pick like we just talked about. It's important to know that all Animation classes inherit from a Timeline class which confers properties related to timing of the animation ... the Begin time, allowing you to delay the start of animation, perhaps waiting for other animations on the storyboard to begin or complete, a Duration property that effects how long the animation should take before delivering the desired result -- how long should it take for our fade in effect, in this case. There's also AutoReverse and RepeatBehavior properties which do what they suggest.A Storyboard is a collection of one or more Animations. You group the Animations you want triggered by a specific event, like a button click, a loaded event and so on. The Storyboard allows you to pair an Animation with a target object. The animation is just a definition of what property should be affected, when it should be affected and how long. We have to APPLY that Animation to a target object. In our case, that target object will be an Image control.In our case, our Storyboard is simple ... we just want one thing to happen. We could add multiple Animations targeting multiple properties of multiple objects, and could even create child Storyboards to better refine how our user's experience will play out. Once we're ready to allow the Storyboard to play, we call its Begin() method. It will in turn kick off all it's child Animations and child Storyboards.For a more complete explanation of animations, I'd recommend you start here:https://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206955(v=vs.105).aspxBack to our situation ... we need to animate each image as it's opened. We'll create an Animation to move the Opacity property from 0 to 1 thereby making it transform from completely transparent into completely opaque. We'll add the Animation to a Storyboard and then call Begin() on the Storyboard.Sometimes the animation is subtle to the untrained eye. To make the effect more dramatic, you can stretch the time from 500 milliseconds to something like 2000 or 3000 milliseconds, or rather, 2 or 3 seconds just for testing purposes.Lines 74 and 75 use a SetTarget and SetTargetProperty syntax to pair up the animation and its target. You see a lot of Set___ and Get___ styled methods in the Windows Phone API, and that's due to the Windows Phone property system we talked about at the very outset of this series.The Windows Phone property system allows us to use attached properties. If lines 68 through 75 were in XAML, it might look something like this:<Storyboard><DoubleAnimation Storyboard.TargetName="ImageControlName"Storyboard.TargetProperty="Opacity"To="1.0" Duration="0:0:0.5" /></Storyboard>(Now, this approach is actually flawed because we would be targeting a single Image control. And as far as I know, you can't use a binding expression inside of the Storyboard.TargetName to make it dynamically apply to every image control in our data template, so this is one reason why a C# approach works better.)I wanted to show the XAML version (flawed though it is) to illustrate what we're doing in our C# code ... in lines 74 and 75 we're ATTACHING the Storyboard.SetTarget and Storyboard.SetTargetProperty attached properties TO the DoubleAnimation object doubleAni, and setting their values appropriately. It looks like we're setting attributes of the Storyboard, but we're ATTACHING attached properties TO the DoubleAnimation.One more curiosity about line 75. We're setting the Storyboard.TargetProperty to a new PropertyPath(OpacityProperty) ... what does this mean?The rules of the Windows Phone property system require the target property of an animation must be set to a Dependency Property. Remember: that's one of the special powers of a Dependency Property -- that it can be animated, unlike regular old CLR properties. Fine, then why do we have to wrap it with the new PropertyPath object. That's difficult for me to explain, and for the sake of brevity let me point you to another article that can explain it with a good example:PropertyPath XAML SyntaxSpecifically, this link points to the anchor "PropertyPath for Animation Targets"https://msdn.microsoft.com/en-us/library/ms742451.aspx#databinding_saIn a nutshell, the PropertyPath is used to specify the property that is the target of an animation. We have a simple case, and so for now, I think it's easier just to understand that the PropertyPath object provides a map to find the dependency property we want to animate.Let's make sure our images fade in by debugging the app:Mine works, and did you notice the half-second fade in? Very nice.We've satisfied the topic of this lesson, but I wanted to add a few more features to our app while we're here. We'll provide feedback to the user to let them know the status of their searches against the Flickr API. 3. Add a TextBlock for "No Photos Found", a Progress Bar and TextBlock for "Loading"Now, lets edit the MainPage.xaml again, sandwiching the LongListMultiSelector with two new passages of XAML:We create a TextBlock element. A TextBlock is a simple XAML element for displaying small amounts of flow content. By "flow content" I mean textual content that dynamically adjusts and reflows the text content based on run-time variables such as window size, device resolution and other user preferences. There's quite a bit to Flow Documents in XAML ... I would point you to this resource for more information: https://msdn.microsoft.com/en-us/library/aa970909.aspx  At any rate, the TextBlock is just a way to put some text on our page.We style it using a built-in Text Style: https://msdn.microsoft.com/en-us/library/windowsphone/develop/ff769552(v=vs.105).aspx#BKMK_TextStyles and most importantly: we set it's Visibility attribute to Collapsed meaning we want it hidden by default. We'll write some logic that will potentially change that in a moment. Add a StackPanel that contains another TextBlock. It also has a ProgressBar element with an IsIndeterminate="True" set, meaning we just want it to keep animating until we're finished with it. We'll toggle this property on and off as we need it. Most importantly, we set the Visibility of the StackPanel to "Collapsed" ... here again, we'll write some logic that will toggle the Visibility as we're performing the web service call in the background. Next, in the SearchResults_Loaded event handler, we'll write the logic for both code passages (above) that I just alluded to.We added code before and after our web services call to Flickr to show and hide the StackPanel's contents, as well as toggle the ProgressBar's animation.Here we show the StackPanel we added (named Overlay). Also, we turn on the ProgressBar's animation by setting the IsIndeterminate = true. In lines 47 through 50, we decide to toggle the Visibility of the TextBlock to reveal the run stating "No Photos found " in, in fact, no ph
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfOur ultimate vision for the app is to allow the user to select one or more photos.Game plan:We'll add a reference to the Windows Phone toolkit so that we can utilize the LongListMultiSelector, an improved version of the LongListSelector we've been using that allows a user to make multiple selections in the list. We'll convert our LongListSelector to a LongListMultiSelector and add attributes to its definition to enable its unique functionality  1. Install the Windows Phone toolkit package and review the samplesThe Windows Phone Toolkit extends what we get out of the box with the Windows Phone 8 API, adding new components and functionality. I'm going to download the toolkit and samples just to see what this can do for us.Visit: http://phone.codeplex.com/And click on the Downloads link. NOTE: THIS CHANGED SINCE THE SCREENSHOT ... Download the solution from the Source Code tab!There's a single download that contains a solution for both Windows Phone 7 and 8 toolkits, as well as sample apps containing all the controls and features. I download it, right-click the zip file and Extract All:  I'll put it in a temporary spot on my hard drive:  And I'll open up the Solution folder, agreeing to the dialogs that warn me about downloading things from the Internet.To run the Sample app:  Right-click the project in the Solution Explorer named: PhoneToolkitSample.WP8. Select "Set as StartUp Project" from the context menu. Now, run the Solution in debug mode (F5).There are dozens of samples featuring the controls and animations / transitions available in the toolkit:  I love the date picker:  ... and the HubTile control which is strangely calming if you watch it for a few minutes:  We're most interested in the LongListMultiSelector sample. It demonstrates several different modes that can be used to enable multi-selectable lists.Click the "Select" button at the bottom:  ... and that puts the list into selection mode. Now, you can select the checkmarks next to each item, then click the icon in the App Bar which has changed to a Delete button:  That's great, however not exactly what we need for our AroundMe project. Fortunately, the control's appearance and functionality can be configured in multiple ways.If you swipe over to the Grid mode panel, there's another example that involves image thumbnails. If you click on an image, it shows a larger version in a light box. However, when you click the icon in the App Bar at the bottom, you can switch to Grid Selection Mode. This allows you to select one or more images. Each thumbnail that's selected will show a red triangle with a white checkmark icon in the upper-right-hand corner. That's what we'll want for the results of our Flickr API call results. This will allow the user to select multiple images to be saved to the phone and randomly used for the lock screen every 30 minutes. 2. Install the NuGet package into the projectTo use the Windows Phone Toolkit package in our existing AroundMe project, the easiest way is to add it with NuGet.Navigate to: https://nuget.org/packages/WPtoolkit/  I love the obvious package installation instructions on the NuGet site.If the Package Manager Console is not already open, go to Visual Studio's Tools menu, select Library Package Manager, then the Package Manager Console sub menu option.At the Package Manager command prompt, type: install-package WPToolkit Assuming you typed it correctly and it encountered no problems, you should see this:  ... and you should now see a reference to the Microsoft.Phone.Controls.Toolkit in the References section of the Solution Explorer for the AroundMe project:  This NuGet package included some additional content ... a folder called Toolkit.Content with a few icon files, and a README_FIRST.txt file:  The README_FIRST.txt file explains the purpose of the icons:  3. Implement the LongListMultiSelectorOk, so now we're ready to modify our SearchResults.xaml page. We'll be upgrading the LongListSelector control to the LongListMultiSelector control, changing a few attributes to enable the enhanced features we'll utilize:  Before we can use it, we'll need to create an XML Namespace entry in the PhoneApplicationPage element at the very top of the page. See line 9:  This XAML Namespace basically says this ... when you see an XAML element prefixed with toolkit, then look in the following assembly and the following CLR namespace for that class' definition. Somewhere in the Windows Phone Toolkit code, there's a namespace defined as Microsoft.Phone.Controls.Toolkit, and it has a class named LongListMultiSelector, among others. So, the compiler parses the element <toolkit:LongListMultiSelector />, and it knows to create an instance of that specific class.In a nutshell, that's all there is to it, but you can learn even more about XAML Namespaces and mapping to custom classes and assemblies here:  https://msdn.microsoft.com/en-us/library/ms747086.aspx#Mapping_To_Custom_Classes_and_AssembliesNow that we have the XAML Namespace defined, we'll be able to reference the LongListMultiSelector like so:  We can salvage most of the code, however we'll ...Change from <phone:LongListSelector to <toolkit:LongListMultiSelector as well as the closing element (line 51). Add the EnforceIsSelectionEnabled="True" attribute and setting. This property is important: it's what actually allows for the multi-selection behavior. Change from <phone:LongListSelector.ItemTemplate to <toolkit:LongListMultiSelector.ItemTemplate as well as the closing element (line 50). Finally, we'll test to make sure we can actually multi-select:  Success! RecapJust to recap, the big take away from this lesson is the Windows Phone toolkit ... what it is, what additional features it supplies, how to incorporate it into our app through NuGet and adding the XAML namespace, and so on. In most cases, all we have to do is think about the features we want to support and focus on those ... most of the heavy lifting has been done by someone else. Nonetheless, we need to be aware that these resources exist and know how to add them into our project.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfWhen our app launches, it will need to ascertain the current GPS position and update the Map control. That could take a little and we want to give the user of our app some visual feedback that all is fine and the application is still working.So, here's the gameplan:We'll create a new ProgressIndicator object and tell our SystemTray to use it when it needs to display a ProgressIndicator I'll create a helper method that will show or hide the new ProgressIndicator  1. Understanding the Progress IndicatorIt's hard to visualize exactly what the SystemTray and Progress indicator look like in an app. I used an example on this page:https://msdn.microsoft.com/en-us/library/windowsphone/develop/ff626537(v=vs.105).aspxTo help me see what it is I'm working with here: In the screenshot (above) I was able to set the SystemTray to a transparent purple color, and set the foreground color to yellow.The SystemTray is ever present even if it's hidden at times depending on what we're doing with our phone. The current time is part of the SystemTray as well.We can create a new ProgressIndicator object and give it to the SystemTray to use as the current ProgressIndicator for our app. We can then show and hide it at will.In our app, I'll use the ProgressBar to provide feedback initially while the app is determining it's GPS position and populating the map. I'll write some logic that will hide and show the ProgressIndicator.First step: create a new ProgressIndicator when our MainPage has loaded ... 2. Create a new ProgressIndicator() object and set it as the SystemTray's current ProgressIndicator. Adding the ProgressIndicator was easy ... now we need to invoke it or hide it as needed. 3. Create a helper method to show / hide the ProgressIndicator The helper method will merely take a boolean which will then turn the ProgressIndicator's animation on or off (line 92) and will show or hide the ProgressIndicator itself (line 93). 4. Modify the UpdateMap() method to use the ProgressIndicator and helper methodNow that we have this helper method, we'll use it in our potentially long running UpdateMap() method. In fact, we'll update the user on the progress by changing the text of the ProgressIndicator throughout the various states of the UpdateMap() method:  Line 43 calls the new helper method to show the ProgressIndicator and turn on the animation. Line 44 sets the initial text of the ProgressIndicator ... at this point, we're starting the process of getting the GPS location. We update the ProgressIndicator's text to let it know we've acquired the GPS location. We hide the ProgressIndicator and turn off the animation. Let's see it in action (F5).  If your internet connection is fast, you might blink and miss the action. If the user has poor reception on their phone, it might be the only thing letting them know that the app is still functioning. RecapJust to recap, the big take away from this lesson is learning what the SystemTray is, and how to pass it a ProgressBar that we can show and hide and change the text of to keep users informed about the progress of long running operations in the app.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfCurrently, we can find all images on Flickr based on the locale of the device, however in our original "low tech mockup" design, we wanted to allow the user to filter the results by a keyword or search phrase. We'll enable that feature in this lesson.Our game plan in this lesson ...We'll modify the layout of the MainPage.xaml to include a Topic textbox that will allow the end user to type in specific search terms to include in our search of images from Flickr. We'll then take that topic and send it to Flickr's web service. That will require that we change the code in a few places to accommodate the passing and receiving of the topic value. We'll then add the concept of radius to the app allowing us to specify the distance from the latitude and longitude for Flickr to include in it's search. I'll also refactor the code to harden it, or rather, make it impervious to accidental or malicious values that are nonsensical. We'll practice "defensive programming".  1. Edit MainPage.xaml: clean up layout, add Search text boxNot depicted in this screenshot, I remove almost all of the boilerplate comments and the comments I've added previously.I change the number of RowDefinitions, as well as their heights. In line 39 I didn't specify a height, meaning I want the default value of *, or rather, star sizing ... " take the remaining available space". Line 40 sets the row height to Auto which means "distribute space evenly based on the size of the content that is within a column or row." We add a StackPanel as a container for the layout of our new Search bar at the bottom of the MainPage.xaml. The StackPanel contains a TextBlock and TextBox to allow for entry. The margin looks like it is missing two values, however that's simple a shortcut for writing: Margin="-12, 0, -12, 0"... it simply means "repeat these values".Now, we'll need to add this notion of "Topic" throughout the entire application. We'll pass it along with the position to the SearchResults.xaml page, we'll pass it to the Flickr web service call, and so on. 2. Modify the Navigation code to pass Topic to SearchResults.xamlIn the MainPage.xaml.cs, edit the SearchClick() method ...We are passing data in query strings ... We talked about query strings already. In this case, I'm concerned that a user may enter characters in the SearchTopic.Text that could be interpreted incorrectly. For example, using an ampersand or question mark could harm the interpretation of the query string. The UrlEncode() method can be used to encode the query-string values or even the entire URL. If characters such as blanks and punctuation are passed in an HTTP stream without encoding, they might be misinterpreted at the receiving end. URL encoding converts characters that are not allowed in a URL into character-entity equivalents. For more information about URL Encoding, check out: https://msdn.microsoft.com/en-us/library/4fkewx0t.aspxHowever, whenever you're working with query strings, whether in HTML or XAML, it's always a good idea to URL Encode, ESPECIALLY if what you're passing in the query string is input by the end user. In the string.Format, I add the "&topic={2}" to pass the Search Topic along to the next page, and ... Add the Url Encoded topic variable to substitute for the third position in the string.  3. Modify the Navigation code to RECEIVE the search topic in the SearchResults.xamlFirst I'll create a private variable to hold the topic value I'm passing to the SearchResults.xaml page ... Next, I'll retrieve the topic value from the query string and save it in the new private variable ... While I'm here, I decide to go ahead and modify my call to the FlickrImage.GetFlickrImage() method. I'll need to pass the topic value to the GetFlickrImages() method that ultimately calls the Flickr web api. Since I've already made the latitude and longitude optional / defaulted input parameters to my method, the topic value must be passed in prior to those (unless I choose to make it optional as well ... but I've chosen not to.) Now that I've added the topic in the call, I need to modify the FlickrImage.GetFlickrImages() method itself:  I modify the method signature by adding the topic input parameter, and ... I pass topic to the getBaseUrl() method call. Now I'll need to modify THAT method as well ...   I modify the getBaseUrl() method signature by adding the topic input parameter I add the "text" parameter to the Flickr API call, per their list of parameters. I modify the line of code that replaces the placeholders with the actual values, adding topic at the end to be substituted into the new baseUrl string. Now, I'm ready to test the results ... I'll search for "observatory" to limit the pics that are returned by the Flickr web service call to only those that have the term "observatory" in their description ...  I get a list of photos back that look different from the list of images I was getting back, and (b) they do all look like they have something to do specifically with the observatory as opposed to a street level view.  However, I suppose I have no easy way to validate these results other than to perform a similar search on Flickr's own website look for similarities between the list I'm displaying in the AroundMe app and the results from their website. I'm satisfied with the results, so I'm not going to take the time to thoroughly check the results. I'll trust that it's working for now.We've satisfied the title of this lesson by adding filtering on the results based on keywords. However, in the time that remains I want to add two improvements to our GetFlickrImages() method in the FlickImage.cs file ... 4. Adding radius and programming defensivelyThe two improvements:First, I'll add the concept of radius ... the Flickr web api allows us to pass in the radius it will search.Second, I'll add some code "defensive code" ... the phrase "defensive programming" is a thought process or approach to writing code. In this case, I'll apply that thought process to mean that I want do some checking of the query string values for latitude, longitude and topic that I'm passing from the MainPage to the Results, and I want to add double-quotes around the topic I want to pass to the Flickr API so the user can add a phrase. If you want to learn more about defensive programming from a high level, a great place to start is Wikipedia:http://en.wikipedia.org/wiki/Defensive_programmingLet's begin by adding the notion of "radius" to our app. I'm not going to take the time to fully implement this in this series. Clint's original application that he gave me will adjust the radius we sent to Flickr based on how zoomed in or zoomed out we are in the Map control. However, I decided to leave that code out of this video series ... first, it will add a LOT of code to the application with come complicated calculations to convert map pixels to radius. Secondly, there's no way to simulate the pinch-in or pinch-out motion in the Windows Phone emulator. Perhaps once I'm finished with this series, I'll come back and add an addendum to how to tackle this scenario. So, for now, I'll merely add the feature for radius, and I'll hard-code the radius to 5 kilometers.I'll modify the FlickrImage.cs ... specifically, I'll modify the getBaseUrl() method's signature to include a radius input parameter ... I default radius the same way I default latitude and longitude: to NaN, or rather, "Not A Number":I'll continue to modify the getBaseUrl() method by splitting out the line of code where I build the url that will later be used in the String.Format(). I want to test the topic, latitude, longitude and radius before adding them to the baseUrl returned from this method. In these cases, I want to only add values to the baseUrl that are valid. Therefore:I re-work this entire section, removing about half of the string I'm constructing. Now that I've removed many of the variable parts (which I'll add back into the baseUrl in #2, #3, and #4, below), I can remove the variables I'll be replacing in the String.Format statement in line 89 and following. I add this gated check to ensure that the user typed something, anything into the Topic textbox on the MainPage.xaml. Assuming the user did in fact type something in, we'll surround it with double quotes (%22 is the ASCII encoding for double quotes) and add it to the baseUrl. I add this gated check to ensure that latitude and longitude are indeed numbers. If they are, then we'll add them in the baseUrl. I add this gated check to ensure that radius is indeed a number. If it is, I'll add it to the baseUrl. Next, I'll modify the GetFlickrImages() method in the FlickImage.cs file:I add radius and default it to NaN I include radius in the call to getBaseUrl() Now, I'll modify the code in the SearchResults.xaml page that calls into the GetFlickrImages() method:Similar to what I did with topic a few moments ago:I create a private variable, _radius, to hold the radius value I include the _radius variable in the call to GetFlickImages() When the SearchResults.xaml page loads, I will grab the query string value "radius". Now I need to PASS "radius" in the query string FROM MainPage.xaml TO SearchResults.xaml ... in the MainPage.xaml:... I merely hard-code this to 5, indicating 5 kilometers.I test to make sure it works, and it does.Again, I've merely hardcoded this value. Ideally, I would allow the radius to match the visible map on the MainPage.xaml. If you want to see a better implementation, take a look at Clint's original implementation. RecapTo recap, the big take away from this lesson was how to grab values from XAML input controls, how to program defensively to make sure we check the input values to ensure they are valid, how to URL Encode whenever you pass values (especially, end user generated input values) in query strings of any kind. Along the way, we were able to expand the usability of our app by all
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfIn this lesson, I want to talk about the keywords we've added to several spots in our source code. The keywords I'm referring to are:async await Task<T> You see all three of them in the GetFlickrImages() method:These keywords are newly added to C# 5.0 and are generally referred to as the new "async"—short for "asynchronous" or "asynchrony"—feature. In a nut shell, this new feature is a simplified way of improving the performance of the app and making it more responsive to the user without the complexity of writing code to use multiple threads. If you call a method of the Windows Phone API or some other library supporting async that could potentially take a "long time", the method will say, "I promise to get those results to you as soon as possible, so go on about your business and I'll let you know when I'm done". The app can then continue executing, and can even exit out of method contexts. Another word for this in computer programming terminology is a "promise".Under the hood, when you compile this source code, the Compiler picks apart the source code and implements a complex series of statements in the Intermediate Language to allow this to happen flawlessly and it does it without the use of multiple threads in most cases.Async is best used for operations that have a high degree of latency, but are not compute intensive. So, for example, we want to retrieve data from a Web API like we're doing in the GetFlickrImages() method. Before async, our app would block the execution of code waiting for Flickr's web service to reply with the data we requested. That could take a second, or two, or three, which is an eternity in computing. But the Phone's PROCESSOR is not busy at all. It's just sitting there, waiting for a reply from the Flickr web service. This is known as "I/O Bound" ... I/O means "In / Out" ... so things like the file system, the network, the camera, etc., involve "I/O bound operations" and are good candidates for async. In fact, the Windows Phone API designers decided to bake async into all I/O Bound operations, forcing you to use this to keep the phone responsive to the end user.Contrast that to a compute-intensive operation such as a photo filter app that must take a large image from the camera and run complex mathematical algorithms to change the colors or the position of each pixel in the image. That could take a long time, too, but in that case, the Phone's processor is hard at work. This type of operation is known as "CPU Bound". This is NOT a good use of async. In this case, you would want to consider a Background Worker which helps to manage threads on the Windows Phone platform. If you are developing in .NET, you may prefer to work with threading via the Task Parallel Library instead, or revert back to managing threads manually, which has been an option since the very earliest versions of .NET.Understanding multi-threading, parallel programming, the Task Parallel Library, even Background Workers on the Windows Phone API are WAY beyond the scope of this series and this lesson. It's a large topic and I'll not lie to you—it makes my head spin. If you want to learn a little more about async and how it applies to the Windows RunTime, check out:Working with Async Methods in the Windows Runtimehttps://channel9.msdn.com/Series/Windows-Store-apps-for-Absolute-Beginners-with-C-/Part-12-Working-with-Async-Methods-in-the-Windows-Runtime... and be sure to read the comments where I further explain this idea.But back to the topic at hand ... async is for those common occasions when you have a blocking operation that is not compute intensive, such as our case here where we are waiting for the HttpClient.GetStringAsync() operation to complete. In this case, we use the await keyword, which says, "I'll get back to you when I'm finished". The thread of execution can continue on through the other lines of code until it absolutely must have the results of that operation. Now, in our case, we attempt to call JsonConvert.DeserializeObject<FlickrData> in the very next line of code, so little advantage is gained. However, we must still use the await keyword because the HttpClient.GetStringAsync() method returns a Task<T>. That method requires we await. You'll see await-able methods with a common convention ... they all end with the suffix Async.Furthermore, any method that uses an await-able method must be marked with the async keyword in their method signature, AND if it is supposed to return a value it must return the value wrapped with a Task<T>. If the method is void, it will merely be marked void in the method signature. Since the HttpClient.GetStringAsync() is marked with await, and our method returns a List<FlickrImage> we must mark our method with async and wrap the List<FlickrImage> with a Task<T>. That essentially means that any method that calls our method can continue executing until it absolutely needs that List<FlickrImage>.Therefore, take a look at the method that calls our FlickrImage.GetFlickrImages() method:That's why in line 37 (above) we must use the await keyword—our FlickrImage.GetFlickrImages() was forced to be await-able (since it used the HttpClient.GetStringAsync()). Notice that we also had to modify the event handler method's method signature adding the async keyword. Since this is what they refer to as a "top level method", the chain of adding async stops here.Again, remind me, why are we doing all of this? In hopes of making our app more responsive. This operation should not be blocking the Phone's processor from taking on other tasks like answering a phone call or running background tasks on behalf of other apps. It won't prevent the user from selecting any of the hardware buttons on the phone and getting an instant response.RecapTo recap, the big take away in this lesson is what async is, how it works, the scenarios it was designed to address, and it's overall purpose—to keep the phone and your apps responsive during long running I/O bound operations.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfUpdate to Video:  Bob made a mistake and left out two key things in SearchResults_Loaded event.  Note the async and await which aren’t in the video.  These are in the text below, source code samples, and the PDF.private async void SearchResults_Loaded(object sender, RoutedEventArgs e) { var images = await FlickrImage.GetFlickrImages(flickrApiKey, _latitude, _longitude); DataContext = images; } Now we have a map and a single image returned from Flickr, we have the basic building blocks for our app. But our eventual aim is to show a list of images instead of just one. So, in this lesson we'll do that by adding a SearchResults page and displaying all the images returned by our search.Our game plan in this lesson:We'll add the AroundMe assets for the tile image and so on We'll add an Application Bar and Search button that will navigate to a new page that will ultimately display Flickr images, sending along the latitude and longitude as parameters We'll add a new page, the SearchResults.xaml page, we'll add a text block to the page, and we'll add code that retrieves the parameters sent from the MainPage to the new SearchResults page and display the latitude and longitude values, just to make sure we are correctly passing that data We'll clean up and refactor the code we've written into class files, and clean up the code that calls our new class file methods so that it more closely resembles our original diagrams / low-tech mock ups of the user interface and user interaction  1. Add AroundMe assets to projectIn the downloads available for this series, there's a subfolder called AroundMe_Assets. We'll be copying (dragging and dropping) the files and subfolders in that directory to Visual Studio to make them part of our project's Assets. First, delete everything inside of the Assets folder ...  ... then in Windows Explorer, drag and drop the files in the AroundMe_Assets folder to Visual Studio's Solution Explorer beneath the Assets folder. When you're finished it should look like this:  The number of files may look the same, but their contents are different ... i.e., the ApplicationIcon.png is for the AroundMe application. There's also an icon called feature.search.png ... it will be used in this lesson as the icon for the Application Bar's Search button. 2. Make sure assets appear in the WMAppManifest.xml correctlyThe assets (images) we copied into our project's Assets folder should match the names of the default assets added by the project template. Just to make sure, let's take a look at the WMAppManifest.xml and see if the new image assets appear as expected.Find the WMAppManifest.xml file in the Properties folder of the project. Double-click to open:  In the WMAppManifest.xml designer, the App Icon should have the appearance of the skyline of my home town (and Clint's home town), Chicago.  Furthermore, we'll want to make sure that Tile Template is set to TemplateCycle, and that the Tile Images (Small, Cycle 1) look like the App Icon:  3. Add an Application Bar and Search ButtonWe've added an Application Bar in a previous lesson, so much of this should look familiar:  I'll create a new instance of the ApplicationBar class I'll create a new instance of the ApplicationBarIconButton class ... in the constructor, I'll reference the location of the Search icon we added a moment ago. I'll add the text that will be displayed under the button, and attach the SearchClick event handler method to the Click event of the button. Obviously, that method doesn't exist just yet. We'll come back to this in a moment and implement it. I'll add the new Search button to the Application Bar. Now, let's go back and implement the SearchClick method (from #3, above). There's a little blue bar under the 'S' in 'SearchClick'. Hover your mouse cursor until a tiny menu appears. It will drop down to another menu option to generate a method stub for the SearchClick method: If you click that menu option, it will generate a method stub as promised. We'll implement that method in the next step... 4. Navigate to a new page, pass data to the pageI add the following code to the event handler method:  In this line, we create a string that represents the path to a page called SearchResults.xaml. We've not yet added that page to our application -- we'll do that in a moment. If you look at the string we're building, we're passing additional information in the form of a query string.  We've already talked about query strings and passing data in a previous lesson. The only wrinkle is that this time we're sending two bits of data from the MainPage.xaml to a new page we've yet to create called SearchResults.xaml. You use the ampersand character & to separate name / value pairs in a query string. Additionally, we're using String.Format() to substitute the actual latitude and longitude values into the Uri string. In line 140, we're using a class called the NavigationManager to Navigate() from the MainPage.xaml to a new page as defined in the new Uri object. The NavigationService not only knows how to navigate from one page to another, but is also responsible for keeping a history of previous navigations so that, when you use the back button on your Windows Phone 8, it can take you back to both the page AND the state of that page as you left it previously. Now that we've created the Application Bar's Search button and have implemented the Click event handler for that button, we'll want to display the Application Bar. 5. Show the Application Bar We'll merely add a call to the BuildLocalizedApplicationBar() method we created a moment ago. Let's test the app:  ... and now at the bottom of our app, we can see the Search icon. Clicking the ellipsis in the upper-right hand corner of the App Bar, we can see it expand to show the Text property of the button as well.If we were to click it, the NavigationService.Navigate() method would probably throw an exception because we do not have a page called SearchResults,xaml in our project. Let's add it. 6. Add a new item to the project, call it SearchResults.xamlRight-click project name in Solution Explorer, select Add | New Item ... In the Add New Item dialog:  Make sure you're in the Visual C# templates Select Windows Phone Portrait Page Make sure you call this: SearchResults.xaml Click Add Next, we'll want to quickly test to make sure the code we wrote correctly navigates to our new page AND sends along those query string values. 7. Validate that the values are being passed correctly between the MainPage and SearchResults pageIn the content panel of the SearchResults.xaml page, I've removed everything, then added a TextBlock control and named it LocationTextBlock.  Now, I'll write C# code to retrieve the values from the query string and display them in the LocationTextBlock ... just to make I can grab those values that were passed in the query string. I create two private fields (variables) to hold the values I'll retrieve from the query string. The OnNavigatedTo() event will fire after the page class has been instantiated, but before the Page_Loaded event fires. This is a perfect opportunity to process the query string. I use the NavigationContext class' Query string property array to get at the individual items in the query string by their name. I convert their data type from string to Double. I wire up the Loaded event for this page. When the Loaded event fires, I set the Text value Formatting in the latitude and longitude. Does it work?  Great!Next, I'll take my first step towards refactoring the code I've written. I'm using that term (refactor) loosely in this context to mean I'm going to re-organize the code more logically. Refactoring is the process of improving the quality (readability, structure, organization, etc.) of the code without changing its function. 8. Refactor the classes into a separate fileAt the moment, I have code in places it should not be. For example, I've implemented three classes:Photo Photos FlickrData ... at the bottom of my MainPage.xaml.cs. We can do better than that.  Right-click on the project name, select Add | New Item ... from the context menu. The Add New Item dialog appears ...Make sure you're in the Visual C# item templates Select the Class item template Change the name to: Photo.cs Click Add Next, open the MainPage.xaml.cs file, highlight the Photo, Photos and FlickrData class definitions ...  ... cut them out of that file, and then paste them into the new Photo.cs file.Photo.cs should look like this:  If this were a real project, I would probably separate each of these into their own files. I do this as a convention for consistency ... each class should be in it's own file so that I can easily locate every class in my project via the Solution Explorer. But that is merely a stylistic preference of mine. This will work just fine.Next, I'm going to implement a class that will wrap the call to the Flickr API web service call. 9. Implement the FlickrImage.cs class Right-click the project name in the Solution Explorer, select Add | New Item ... from the context menu. When the Add New Item dialog appears ... Make sure the Visual C# item templates are selected Select the Class item template Change the name to: FlickrImage.cs Click Add Next will involve writing a lot of code. I'll explain it after the code passage below:The FlickrImage class has a dual purpose. (a ) An instance of this class represents a single image's Flickr URIs at different image resolutions, and (b ) It has a public static method (GetFlickrImages()) that knows how to call Flickr's API and retrieve a generic List<FlickrImage>. Perhaps it would be a good idea to separate these into two separate classes and class files, but I'll leave it as is for now.I implement the two instance member properties representing the URIs pointing to two sizes of each Flickr image we'll use in this project. The smaller image will be u
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfIn this lesson we'll search for Flickr photos near the geocoordinate determined by our phone.Many of the most popular phone apps have some interaction with web-based services ... so the app allows users to get at their own data that they've stored "in the cloud", or they provide access to data in order to make it available in some fresh new way.As developers, we can access the web-based services programmatically IF they expose a web API. A web API is usually just an HTTP based method call ... the URL includes the input parameters of the method call, and the web API will return data back in some standard format. Nowadays, that is usually XML or JSON, JavaScript Object Notation.Flickr is a great example of a web service we can leverage in our apps ... They have a vast amount of image data that we can search via their web-based API. All we need to do is call one of their methods and then parse the data they return to us.Our game plan in this lesson:We'll do a little investigation into the Flickr API to see how we can leverage it in our app We'll get setup with Flickr so that we can make calls to their API, and get examples of how to call the method we want to utilize We'll write code in our app to make calls to the Flickr API When we get data back from our call to the Flickr API we'll figure out how to parse through it and actually obtain pictures that we can display in our app This is a VERY long lesson, but it's crucial because it will serve as a proof of concept that our idea will actually work. We'll see how all the pieces come together and then the rest of the series will be adding improvements and refinements to what we do in this lesson.1. Become familiar with the flickr API site, sign up for developer accessNavigate to: http://www.flickr.com/services/api/This is the home page for Flickr's API.Before you can take advantage of the API in your app, you'll need to sign up for a developer account.There should be an obvious Sign Up link somewhere on the top of the page. I won't walk through that process ... it's likely to change over time. I was able to use my existing Yahoo! ID to sign up for a developer account. It's free and easy to get started, and you'll need your own account so that you can get your own API Key.Most companies exposing APIs over the web want to ensure that developers are complying with their terms of service, or they want to track usage by app to better understand how their APIs are being leveraged. I suppose in extreme cases the company may want to shut down an app that is abusing the service. This is why most require a unique identification for the developer and the app through the use of an API Key. Flickr is no different.To get an API Key for the AboutMe app, find the "API Key" somewhere on the Flickr API homepage.This will list all of the API Keys you were granted for your apps. You'll need to use a different API Key for each app you intend to use with Flickr's API.Ultimately, you want to create a new API Key by using the "Get Another Key" button.For now, our app will not make any money, or it's not currently commercial but might be in the future, so choose "Apply for a Non-Commercial Key":They want to learn more about the app you're building. You can copy my text if you want. You'll also need to agree to the terms and such:When you fill out the form and click the SUBMIT button, you should receive your API Key.Since I'm (probably) not supposed to legally reveal my key, I've blurred some of it out. Keep the Key and the Secret available. We'll need them later in this lesson.Back on the main Flickr API page, you see a list of all the web callable APIs available on Flickr. You can literally perform any conceivable operations using Flickr as the backend storage and processor for your photos and create new applications that "mash up" Flickr's functionality with some of your own. That's exactly what we want to do ... combine Flickr's search capability for photos -- specifically searching for photos that were taken geographically in the same place the user of our app.We want to learn more about the flickr.photos.search API ... how do we call it? What options can we send along to specify geolocation we want to search for? 2. Learning about Flickr's search APIWhen you find the API you're looking for (i.e., flickr.photos.search), click the hyperlink to learn more about that web API method.On this page dedicated to the flickr.photos.search web method, we can see which input parameters are optional and which are required, the purpose / meaning of each parameter, the expected format of the parameter value, and so on.We also can see a list of error codes returned by the web method to the caller ... this might help us interpret any error codes we receive.There's also an "API Explorer : flickr.photos.search" link which takes us to a web page where we can experiment and learn how to call that particular web method. By clicking the "Send" check box and supplying a value, we can see the format that our web method call should take. I'll input the a number of options such as the optional latitude and longitude for the John Hancock Center, and add optional text "observatory":  I'll add an optional radius of "1". I learn that the default "radius_units" are in kilometers, so by adding a "1" I'm saying "search within a 1 kilometer radius of the geocoordinate I'm specifying".I also will choose to send the output of my query to JSON, the JavaScript Object Notation.I'll choose the radio button next to "Sign call with no user token".Once I've added my settings, I'll click the "Call Method..." button. When I click the "Call Method..." button, a large textbox will appear beneath the button containing sample data in JSON format, as well as the URL that was constructed based on my selected options. Both of these will be important for me in just a moment. 3. Setting up our project to use the Flickr APIBack in my Visual Studio project, I'll need to prepare for making my first call into the Flickr API. I'll want to appropriately brand the app by changing the app and page titles. I'll just hardcode them this time and not use the resources file. I realize this will limit my app to just English speakers. I can always come back later and change this.  Change the Text attribute to "AROUND ME" Change the Text attribute to "pictures near ..." My next changes will be in the ContentPanel.  Add three RowDefinitions at various heights Put a control in each of those new rows. I create a TextBlock called "ResultTextBlock" for row 1. I create an Image control called "FlickrImage" for row Move the Map to row 3.  4. Programmatically calling the Flickr API via HTTPMy goal is to populate the Image control with a single image. Later, I'll add a search results page that can display all the results. For now, I just want to hack something together to figure out how to call into the Flickr search API programmatically and get results. I'll make it work correctly later.  I comment out the SetView() and instead use the Map's Center and ZoomLevel properties just to show how to perform the same task using only the The ResultTextBlock should not be here I want to make a call via the web and I know there's a class in the Windows Phone 8 API called HttpClient. However, I don't have that package installed in my project. I can find that package on NuGet at: http://nuget.org/packages/Microsoft.Net.Http  NOTE: Since I took this screenshot, this package no longer requires the -Pre argument.I pay particular attention to the way you install the package using the Package Manager Console: Install-Package Microsoft.Net.HttpTo open the Package Manager Console: Tools menu Library Package Manager Package Manager Console This will open the Package Manager Console by default in the bottom area of Visual Studio (unless you docked it somewhere else in a previous session).You'll type in the install-package command at the Package Manager prompt: Install-Package Microsoft.Net.Http If all goes smoothly, you'll see the a number of messages appear indicating success:  Now when you look at the Solution Explorer under the References folder, you'll see three new references System.Net.Http.*  Now we should be able to resolve the reference for the HttpClient class. However your mouse cursor over the blue dash under the "H" in HttpClient to reveal a drop-down menu. Choose the: using System.Net.Http;... option to add a using statement to your MainPage.xaml.cs. Now I work my way through the process of building a URL to call Flickr's search web API. I'm using that URL from the "API Explorer" as my template, substituting the optional parts like the api_key, license, lat, lon and so on.  First I add licenses that I want to search through. I only want to include licenses that have limited or no copyright licenses associated with them to avoid any legal problems. I could hardcode this string, however I would prefer to construct it so that I could modify it easier and more consistently in the future. As you can see I'm switching out the commas in this string for %2C ... this is a form of URL Encoding. Leaving certain punctuation in a URL like commas, periods, quotation marks, question marks, ampersands and so on could produce unpredictable results because they have a specific meaning and usage when the URL is parsed by the web server. So, to bypass that, we URL encode those characters. After the web server software is finished parsing the URL, those characters will be decoded and understood the way we want them to be understood. It's a form of packing and unpacking a suitcase that you'll take on a flight with you. Here I've separated out my Flickr API Key because I may want to replace it later. Here I create the URL as a string with the replacement codes -- like {0} and {1} -- for use in the next line of code ... Here we use string.Format to perform the replacement of the code -- {0} and {1}, e
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfIn the previous lesson I was able to hardcode a GeoCoordinate object and pass it to the Map control to set it's position. However, for our app, we will want to retrieve that information from the phone. The Windows Phone API has a Geolocator class that will use the phone's GPS system to determine where in the world it is.Here's the game plan:We'll experiment with our UpdateMap() method to learn about the Geolocator class, how to set it's accuracy and obtain the current position. We'll learn about other classes in the Windows Phone API that allow us to work with the map and the locale of the user We'll configure the Windows Phone Emulator and set its position to a specific place, namely, the John Hancock Center in Chicago. I have a special affinity for Chicago and for that building specifically that I'll tell you about later.  1. Modify UpdateMap() to retrieve it's position from the Geolocator classWe'll pick up where we left off in the previous lesson, updating the UpdateMap() method as follows: We create a new instance of the Geolocator class and set it's DesiredAccuracyInMeters property to 50 (meters). We call the GetGeopositionAsync method.  At this point, I'd like to point out the best article I read on the process of acquiring the Geoposition of the phone and why there are several factors to consider. Actually, It's a blog post on the Windows Phone Developer blog from Daniel Estrada Alva, a software development engineer on the Windows Phone team.  http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/11/30/acquiring-a-single-geoposition-in-windows-phone-8.aspx There's a keyword you may not be familiar with in line 40: the await keyword. This corresponds with the async keyword I added to the method's signature in line 34. Just how this works and why I would like to save until a later lesson when I take extensively about the new await functionality in C# 5.0. For now, just understand that the purpose of this is to keep our application responsive while potentially long running tasks are executing. In this case, the phone may take a long time to acquire the current location using its built in GPS hardware. While it is acquiring the location, the user's phone, and even our app, should continue to be responsive to the user's input. Again, more later. The Geoposition object has a collection of coordinates. However, we have to do a little conversion because the Map control requires those coordinates be in a GeoCoordinate object. Finally, we pass the GeoCoordinate we just created to the SetView() method. When we run the app (F5), we can see the result:  ... the result is that the Map control is zoomed into Redmond, Washing, the home of Microsoft's main campus. This is the default position of the Windows Phone Emulator. 2. Use the Emulator's Additional Tools to change the virtual location of the Emulator for testingSo, how do we change the Emulator to use a different latitude and longitude? I click the double chevron to open up the Additional Tools panel. I click the Location tab at the top. I the words "John Hancock, Chicago" into the Search textbox and hit the Enter key on my keyboard. This shows me a different map ... a map of downtown Chicago positioned at the John Hancock Center. Excellent.I'll use the primary (left) mouse button to add a pin on that location.  By adding a pin, I've set the Current Location to the correct latitude and longitude for the John Hancock Center.However, sometimes it takes a while for the phone's GPS to catch up and refresh. What I've found works best is to exit out of the AroundMe app, go to the Windows Phone 8 application list, open Maps and wait for the phone to reposition to the desired location. When I do that, after about 10 seconds, the Maps program repositions to downtown Chicago.  Now, I re-run the app from the Application List (I don't need to stop and re-start the app from Visual Studio) and it should pick up the change in GeoPosition. It works!RecapJust to recap, the big take away from this lesson is how to use the Geolocator class to interface with the phone's GPS hardware to retrieve an instance of the GeoPosition class. The GeoPosition class has a number of interesting details, but for our purposes we care only about the longitude and latitude, which we can use to construct a new GeoCoordinate class in order to center the Map control. We learned how to configure the Phone Emulator's Location to make it think it is at a specific place in the world to test various location scenarios.
Source Code:  https://aka.ms/absbeginnerdevwp8Now that we've finished our first app, let's move on to building a second app. This time let's build an app that is both location-aware and social in nature... so, it will use the Phone's GPS to determine where the current user is standing, and then use the latitude and longitude to search for photos that others have taken within a few meters of where the user is standing.How will we do that? We'll call on Flickr, the social photo sharing website, to provide the data. Whenever you take a photo with a camera that supports Geotagging, extra meta data is added to the photo that includes the latitude and longitude (amongst other) data. Then, when you upload the photos to Flickr, it will store that extra data and make it available so that others can search based on a specific latitude and longitude.Our app should not only allow me to search for photos "around me", but it should be able to let me pick my favorite Flickr photos as lock screen background images. That would be cool!Now that we have some ideas of how it should work, let's spend a few moments mocking up how we want to app to behave. That will be the target that we build to throughout the remainder of this series.Our game plan in this lesson:We'll start by brainstorming using a low-tech mockup to design the interactions and screens we want in our app. We'll create a new project and take some preliminary steps towards building our app by including a map control in our project ... Even though we haven't designed the app just yet, I anticipate that the map control will come into play at some point so we'll learn how to use it in this lesson. 1. Create a low-tech mockup for the AroundMe app.Again, we should spend some time thinking about the functionality of the app, about the interaction between the user and the app, how the information should be displayed to the user and we'll do that through a "low-tech mockup" using the templates available from Microsoft: After some brainstorming, we come up with some good design ideas. The MainPage will show the user the map control that displays the user's current location. Below that, a Textbox where the user can add an optional search phrase to refine which photos are returned. And below that, an application bar with a search button.When the user clicks the search button, we'll make a call to Flickr's web-callable API using the user's current locale and the search phrase. We'll get back a list of images that we'll display in a grid. The user can select photos and click a button in the application bar which will cache those photos on the phone and randomly use them as the lock screen image. This will require we use a background agent to run every 30 minutes or so.Now that we have a basic idea of the interactions, functionality and screen elements we'll need, let's start building towards that design. 2. Create the AroundMe Solution and ProjectYou should be familiar with this process already, however for the sake of completeness, begin the process by going to the File menu, New | Project ... submenu. That will open the New Project dialog: Make sure you're in the Visual C# | Windows Phone project templates. Select the "Windows Phone App" project template. Change the name to AroundMe. The Solution name should automatically change as well ... just make sure it has already been changed to AroundMe. Click OK.The MainPage.xaml should open in the main area of Visual Studio. 3. Add a Map Control from the Toolbox to the visual XAML EditorUp to now, we've been working with XAML directly. Now that you're comfortable with typing in XAML, I feel comfortable to showing you a shortcut ... you can drag elements from the Toolbox into the visual XAML Editor:When you do that, there are a few side effects. See what happened to me: In my case, it created a left-margin of 368 and a top-margin of 101. That's not what I wanted, but I can easily edit that out in the XAML itself.It's for this reason that I prefer to work directly with XAML ... especially if I remember the name of the control I want to use.However, in this particular case, there's a huge upside to using the drag and drop technique. Look at the code that was added in line 8:  By dragging and dropping the Maps control, an XAML Namespace was added to the XAML document. This is necessary because the Maps control lives in a different Namespace and Assembly from the other controls I had been using.Nonetheless, I now have a Map control. I edit it to simply sport a Name attribute. I want this because I know I'll be working with it in C# in just a moment:  If I were to try and run the application at this point (F5), I would experience an error at runtime:  The problem is that the Map control requires the Mapping and Location capabilities of the phone and we've not told the Windows Phone operating system we want to use those capabilities in our app.The mapping functionality of the Windows Phone 8 Operating System has changed dramatically from the previous version based on Bing maps. The new mapping features were built in conjunction with Nokia and are more integrated into the Phone's operating system than before in an effort to make the maps more performant. So this is why we need to request permission to use this capability of the phone ... it is now a core feature of the phone.To learn more about the rationale for the changes to mapping in Windows Phone 8:http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/24/the-windows-phone-map-control.aspxTo remedy this, we'll make changes in the WPAppManifest.xml ... open the WMAppManifest.xml file:  We'll need to add two Capabilities:  In the WPAppManifest.xml visual designer ...Choose the Capabilities tab. Place a check next to ID_CAP_LOCATION. Place a check next to ID_CAP_MAP.Save your changes and re-run the app (F5).  The Map control appears, but it's at a very high level because no location is set. We'll do that next.In the MainPage.xaml.cs:  We'll handle the Loaded event for the MainPage ... use the little technique I demonstrated earlier to create a method stub for MainPage_Loaded (hint: hover over the M in "MainPage_Loaded"). We'll create a helper method calls UpdateMap() that will contain the code to set the coordinates and other information to initialize the Map control. Create the method stub for the UpdateMap() method.Inside the UpdateMap() we'll add the following code:  The SetView() method combines several property settings into one convenient call. We'll pass in a GeoCoordinate hardcoded to a specific place (in Chicago ... more on that in a moment) and a scaling factor of 17. You can experiment with these numbers. 19 is zoomed in really close and 5 is really far away.By the way, I've suffixed each of the values with the letter "D" which is for Double ... this is just a way to ensure we're working with Double literals.Now I'll test to make sure it works (F5). And it does! RecapTo recap, the big take away from this lesson is how to use the new Map control in the Windows Phone 8. We'll become even more familiar with it as we go through these lessons, but at a minimum, we know that it requires us to set a Capability in the WMAppManifest.xml file. We also learned how to change the focus of the map and the zoom level. We learned about the GeoCoordinate class that represents a position on the globe based on its latitude and longitude. We still need to learn how to retrieve the current position of the Phone, and we'll do that soon, but this is a good start.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfNow that we've finished the app, it's time to test it and submit it to the Store.A word of caution before we continue ... at a minimum, your users expect your app to be solid and to look professional.With regards to creating a solid user experience, there's only so much you can do by yourself because you have the curse of knowledge. As the developer, your knowledge of the flow and "normal operation" of the app creates a myopia. You'll quickly find that your users will brake the app in new and creative ways. So, I would spend a of time thinking about the states of the application, particularly any scenario that accepts information from the user in input controls or dialogs. I would spend time thinking about exception handling and messages back to the user to help diagnose the problem. I would think about inputs and outputs and edge case scenarios ... What if they use strange characters outside of the ASCII or Extended ASCII range? What if they add two sounds with the same name? What if the program runs out of battery while the user is recording a sound? What happens if the user clicks one of the hardware buttons while recording or playing back a sound? What if the user fills up Isolated Storage with custom sounds? As it stands now, that would be a problem because we don't have a delete sound feature in the app.With regards to a professional appearance, here again you have the curse of knowledge and quite possibly a cognitive bias that leads you to think the flow and aesthetics of the app look great when your users think otherwise. Getting feedback, especially from someone who may study design, usability, etc. could prove invaluable. I would get them involved early and often throughout the development process. The beauty of the Windows Design language, formerly known as Metro, is that it pushes you towards a certain aesthetic sensibility. You should study the recommendations from Microsoft in this regard:https://developer.windowsphone.com/en-us/designAt any rate, even when you're getting creative and thinking through the functionality of your app, you'll miss something. That's why it's good to:Let others see your work, especially those who are not your close friends or family. You want honest feedback. Your family and friends won't want to hurt your feelings if they don't like your work. Use the Beta test feature of the store before you attempt to sell the app. Now you're opening your app up to more scrutiny and feedback, however it's better you hear that feedback in beta rather than hear that feedback in the form of negative reviews that pour in and kill your app's chances at success. Even after you've sold the app (or distribute it for free), be responsive to customer emails, questions, feedback, etc. Whether you realize it or not, once you publish an app you're now running a business. From now on you need to be the friendliest guy on the planet. If someone asks for a new feature, ask them for more details and genuinely give serious thought to whether that's a viable feature to add or a bug to fix. If someone is frustrated and uses harsh language or tone against your app, you gain absolutely nothing by returning the salvo. You need to grow thick skin, swallow your pride, and be the bigger person. From personal experience in handling customers who are displeased over the years, you can turn an enemy into a friend more often by not by choosing your words carefully. May I recommend the time-honored book, How to Win Friends and Influence People by Dale Carnegie. Dedicate a URL and a few pages to your app. Include FAQ's so people can self-serve for the most common issues. Understand the impact of low-memory on your app. I suspect most app crashes have to do with memory constraints, or the failure to close a resource like the file system when you're finished working with them. The game plan for this lesson:We'll perform some compliance testing to make sure our app has a chance to be included in the Store We'll submit our app to the store 1. Run the Store Test KitTo evaluate the readiness of our app for the app store, we'll use the Store Test Kit. This will automatically test a few scenarios and suggest other manual tests for you to conduct. Furthermore, it works as a check list for the items you'll need to submit to the store, like promotional images and the like.To open the Store Test Kit, go to the Project menu select Open Store Test Kit:  This will open a new page in the main area. Notice there are three tabs on the left:  The Application Details collects basic data about the app, including a larger version of the main tile (300 pixels by 300 pixels) for the Store and screenshots of the app. If you use the Phone Store, you can see that each app has a page with descriptive text and details about the publisher, a page with the ratings and reviews for the app, and a page of screenshots.The Automated Tests tab will perform a few tests to ensure the validity of the XAP deployment package, and will ensure the images (from the Application Details tab) are in place as well.  The Manual Tests tab has a number of suggestions for you to test on your app before submitting it.  To the right of the test status (think of this like a check box that you will manually check off) and the name of the test is the description of the test and how to perform the test, what constitutes failure, etc. If you attempt to run the tests without changing anything in Visual Studio by clicking the "Run Tests" button on the Automated Tests tab ... ... you'll probably get the following warning / error:  There are several issues we'll need to correct, but the first one is that we need to create a Release version of the deployment package. We've been using a Debug version which includes additional files used to sync up the execution of the code on the Emulator or the Device with Visual Studio so that you can set break points, step through code, and so on.Now we'll need to create a release version. Before I do that, let's confirm that Visual Studio will create a Release version that is configured to be deployed to "AnyCPU" per the instructions of this dialog. In the toolbar, I'll select the drop down list next to the Run button and select Configuration Manager:  The Configuration Manager dialog appears:  In the Action solution configuration drop down list, I'll select Release ...  And I'll review the Project contexts in the main area, ensuring that the Configuration is set to Release and the Platform is set to "Any CPU". If the settings are right (and they should be by default), then I'll Build the Solution (Build menu, select Build Solution). If all goes well, the Output window should indicate success. If it doesn't you'll obviously need to fix that before continuing.  Now that we have a valid release version of our XAP deployment package, we'll "Run Tests" again ...  ... this time, we see that we failed with Iconography and Screenshots. Before I set those, let's take a look at the button further down on that page ... the "Start Windows Phone Application Analysis" ...  Clicking this button will add a new .sap file which is a blank performance log file that will capture data about the performance of your app as it runs. The log file will then be poured over and reported on to let you know how well it runs in certain situations:  That .sap file is loaded into the main area of Visual Studio:  Rather than spend time talking about the different types of data and reports you can generate from the monitoring and profiling options, I would recommend that you read what the help has to say about it:https://msdn.microsoft.com/en-us/library/windowsphone/develop/jj215908(v=vs.105).aspxAt this point, I'll merely:Choose the App Analysis monitoring option, then ... Click the Start Session link at the bottom. The app will load in the Emulator and you'll see Visual Studio display a monitoring message:  At this point you should put the app through its paces and perform your typical use cases, and perhaps even some edge cases. When you're finished testing the app ...Click the "End Session" link The collected data will be analyzed:  ... and a report will be generated ...  The report includes some very interesting details about the app that could help you determine its readiness for the Store. I think one of the most important things to look at is the battery consumption and the max memory used.Now that we've completed this test, I'll make sure to ready the images needed for the Store, such as the Store Tile (300x300) and the screenshots. I use the Emulator's Additional Tools to capture two main views of the SoundBoard app:  And I've chosen to save them into the Assets folder of the project. However, in retrospect, I probably would have put them somewhere else ... perhaps another subfolder of the project so I could get back to them more easily and have less confusion about the names and such.  I add the two screenshots to the Application Screenshots section of the Store Test Kit:  However, if you were to run the tests again, it will still fail because you need to provide versions for ALL THREE RESOLUTIONS.In the Application Screenshots section of the Application Details page, use the drop down to reveal the other screen resolutions and populate them with screen shots using the different versions of the Emulator to capture screen shots at those resolutions.  TIP: When I went to upload the images to the Store, it provided an option to create / scale the various versions of these files based on the WXGA version. However, if getting the Store Test Kit to pass successfully is important to you, then you'll need images for each of the three resolutions.After supplying all of the required files, I was able to get the automated tests to pass:  Again, I still have manual tests to consider, as well as my own internal testing I want to perform, but at least this helped me get the assets and
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfThe final step will be fun ... we'll animate the reel object on our record audio screen. We want it to rotate as we're recording ... that's a nice visualization of what the app is doing, a nice visual cue to the user that they are in the middle of an important operation with the app.Our game plan in this lesson:We'll create a Storyboard that includes an animation to rotate the Ellipse and the other objects. We'll programmatically start and stop the animation ... but first we'll need to learn a little about creating animations on the Windows Phone. 1. Declaratively define the animationBefore we dive too deeply into the topic of animation, I want to discuss it at a high level. Once we're comfortable with how animation works in XAML UI frameworks, we'll have a bit more confidence to apply a specific animation to rotate our reel.First, its important to realize that XAML controls like the Grid, Button, etc. are defined separately from animation definitions. You can create an animation that is applied to different controls as needed. An animation is associated with a control and then triggered by some event. In our case, we've already defined the Grid and the shapes that will comprise the reel. We'll soon define an animation and associate the two, then we'll write C# code to trigger the animation. Again, we'll do all of this before the end of this lesson.Animations are made up of a Storyboard object and at least one Animation object.Let's start with the Animation. First, there are several different types of animation data types. We're using a DoubleAnimation data type because we want to move a property (the Rotation property) from 0.0 to 360.0—the angle of the animation every 4 seconds. In other words, we want the Grid to rotate every 4 seconds. Besides the DoubleAnimation, there's also a ColorAnimation class for animating between two colors, and a PointAnimation for modifying an objects X Y coordinate or its size.An Animation is basically a timeline combined with a result. The results are determined by the specific Animation class you pick like we just talked about. It's important to know that all Animation classes inherit from a Timeline class which confers properties related to timing of the animation ... the Begin time, allowing you to delay the start of animation, perhaps waiting for other animations on the storyboard to begin or complete, a Duration property that effects how long the animation should take before delivering the desired result—how long should it take for our fade-in effect, in this case. There are also AutoReverse and RepeatBehavior properties, which do what they suggest.A Storyboard is a collection of one or more Animations. You group the Animations you want triggered by a specific event such as a button click, a loaded event, and so on. The Storyboard allows you to pair an Animation with a target object. The animation is just a definition of what property should be affected, when it should be affected and how long. We have to APPLY that Animation to a target object. In our case, that target object will be the Grid that contains our shapes representing the reel.Our Storyboard will be simple since we just want one thing to happen—a rotation from 0 to 360 degrees every 4 seconds. Once we're ready to allow the Storyboard to play, we call its Begin() method. It will in turn kick off all it's child Animations and child Storyboards.There are 4 possible transforms that you can animate as listed and diagrammed on this page:https://msdn.microsoft.com/en-us/library/ms750596.aspx(I realize that this article is specifically for WPF, but many of the concepts transfer to the Windows Phone API.)RotateTransform ScaleTransform SkewTransform TranslateTransform ... as well as other attributes you can change with the ColorAnimation and the like. There's a lot more to learn about animations, and for a more complete explanation of animations, I recommend you start here:https://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206955(v=vs.105).aspxNow that you have the basics of StoryBoards and Animations, let's modify the Grid containing the shapes that comprise the reel graphic. You'll recall that the large ellipse and the smaller rectangles and ellipse are all contained in a Grid for layout purposes.To get them to all move correctly at the same time, it is easier to just animate / rotate the grid (rather than each individual shape):I'll add a name so I can access it programmatically, and I want to indicate that I want to entire grid and all its children to animate together, as a group, or rather as a composite:Add the programmatic name attribute. I set the RenderTransform property to CompositeTransform. Essentially, what I'm saying is that I will transform the contents of the Grid as one complete unit. I've not provided the details of HOW I'll transform the grid, just the fact that, for the purpose of performing transformations on the Grid, I want to treat the Grid and its children as a group. I'll define HOW I'll transform the grid in a Storyboard. Near the top of the RecordAudio.xaml page (beneath the PhoneApplicationPage declaration), I will add a Resources section:We're creating a Page-level resource. We're creating a Storyboard ... because it's Page-level, we could re-use this in other spots in our page. We'll give the Storyboard a name, "RotateCircle" and once it starts, it's repeat behavior should be "Forever". We'll control start and stop programmatically. I'll access this Storyboard programmatically by it's name in a moment to start / stop it. We'll build a DoubleAnimation object. Why DoubleAnimation? As we discussed at the outset, we want to modify the Rotation property (see the Storyboard.Target property) from 0.0 to 360.0, which are numerical (and therefore will require we use the DoubleAnimation). We set the duration of the animation to 4 seconds and so, in 4 seconds, we want to increase the Rotation value starting at 0 and increasing to 360. We set the TargetName, which is the name we gave the Grid containing our reel. The TargetProperty is tricky ... we have to write it this way due to the fact that we're working with a CompositeTransform ... as I mentioned a moment ago, we want to animate the Grid AND ITS CHILDREN. Otherwise, we could simply set the TargetProperty="Rotation". 2. Programmatically start and stop the animationWhat comes next is easy now that we've declaratively defined the animation. We'll start and stop the animation based on the state of the ToggleButton:While recording, start the animation. When finished recording, stop the animation. If we were to run the application at this point, we would notice an odd behavior while recording:  The reel is not rotating in place, but rather, it is rotating around the page. This is because we didn't define the spot of origin for the transform to take place. Instead of at its default X Y position (0, 0 ... upper left-had corner), we want it to be in the middle (.5, .5), so we'll set the RenderTransformOrigin to that position:  Now when we re-run the app, the reel spins instead of traveling:  3. Deploy to physical Phone DeviceJust for fun, I wanted to see this working on my Nokia Lumia 920, so I connected my device to my computer with a USB cable and used the drop-down next to the Run button on the toolbar to select Device:I was able to run the app, record and save sounds, even hit break points just like I could using the Emulator in Visual Studio. Excellent. RecapTo recap, in this lesson we learned about animation using Storyboard and the relation to Animation classes. We talked about the different types of animations and transforms you can add to your app. Then, we learned how to programmatically trigger the storyboard and how to stop it. We learned about things like how to modify the rotation animation's starting point by changing RenderTransformOrigin attribute. The big takeaway is that if you can imagine it, there's likely a way to accomplish it given the wealth of animation options in XAML and the Windows Phone API.Now that we've finished our first version of this app, I want to challenge you to add some functionality on your own. I haven't yet added these features myself, and there's no denying that they would require a day or two to research, develop and debug, but here's what I would like you to try and add:Figure out how to add images to each item. You'll need to manipulate the data model to accommodate an associated image file, and you'll have to add image files to the project, add an Image control to the DataTemplate, and bind to it. Actually, if you watch the rest of this series you'll get some hints on how to accomplish this because we'll be binding images to tiles (among other things) as we create our second full app. Figure out how to delete items. Right now, if you add a custom sound, there's no way to get rid of it. That's an unfortunate limitation. Clint suggests you use a Context Menu from the Windows Phone Toolkit (which we'll learn about that when we work on the next app as well). Figure out how to pin sounds to the Start page. That's something I've never tried to implement, but I know there are tutorials out there that can lead you in the right direction. Are there other features that would make this app cool? Try adding them or share them as challenges to your fellow students in the comments below the video.Now we have to move on ... we'll begin our second app in the next lesson.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfAt this point, we are recording audio and saving it to a temp file on the app's IsolatedStorage. Next, we need to allow the user to permanently save the sound providing details like the display name for the new custom sound.The game plan:Add an event handler method to the "save" application bar button We'll manage the state of the application bar ... it should only be visible if a temporary audio file has been created and is ready to be saved permanently We'll use the Coding4Fun Toolkit once again, this time to display an InputDialog to capture the name of the new custom sound audio file We'll serialize the data for the CustomSounds into a JSON file And we'll modify our data model to also load the CustomSounds JSON file to create new instances of the data model for those custom sounds  1. Add an event handler method to the "save" button and manage application bar stateEarlier we created the application bar for the RecordAudio.xaml page by enabling the BuildLocalizedApplicationBar() method. So all we need to do is make it active: In line 43 I add an event handler to the Click method using the technique we've utilized throughout this series ... while we're at it, use the other technique I've demonstrated to generate a method stub for the SaveRecordingClick method (hover-mouse-over-blue-dash to reveal an Intellisense menu option to generate the method stub) In line 46 I immediately hide the application bar ... we only want to show it when we have a sound to save (after the user records a custom sound) Next, we'll enable the application bar after the user stops recording. In the RecordAudioUnchecked() method, we'll set the IsVisible property to true (see line 67, below): 2. Use the Coding4Fun Toolkit to display an InputDialog to capture the name of the new custom sound audio fileIn the previous step we added a method stub for the SaveRecordingClick() method.I'll replace the line of code that throws an exception as a reminder and write the following (line 51, below):Since the InputPrompt is from a different namespace than the others we've utilized so far, we'll need to add a using statement (using the hover-over-the-blue-dash method to reveal the contextual menu).Next we'll configure and show the InputPrompt:Here we set the Title and Message we want to appear in the InputPrompt We attach an event handler method (and generate the method stub using techniques I've demonstrated before) to the Completed event ... we'll tackle that in the next step Once configured, I show the dialog When the user types in a name for the new custom sound and clicks the checkmark button, the FileNameCompleted() event handler method will fire. We'll ensure that the InputPrompt was exited properly by the user by checking the result. We'll check the PopUpResult that was sent into this event handler method as an input parameter. If the result is "OK" then we can perform the logic necessary to save the temporary file as a new "permanent" sound. See the code I added below, as well as the code comments which give me an outline of the "next steps" I'll want to perform:  If the user correctly typed in a new name and clicked the checkmark button to exit the InputDialog, then we'll perform the tasks required to save the custom sound and make it available in the Custom Sounds view of the Sound Board. Finally, we'll navigate back to the MainPage.xaml Between callouts 1 and 2, above, are an outline of what needs to happen in order for this to work correctly. Before we attempt to implement those ideas, let's make sure the flow works as we would expect so far by running the application.I record a custom sound by using the ToggleButton. When I stop recording, I in fact see the application bar appear:  When I click the disk icon to save the custom sound, it displays the InputDialog:  And when I type in a new sound name and click the checkmark icon, the dialog disappears and returns me to the MainPage.xaml. Great!Now, for the hard part ... we'll perform those tasks I outlined in the code comments. 3. Save the sound file into a permanent IsolatedStorage area, serialize the data for the CustomSounds into a JSON fileAt this point we have a custom sound recorded and stored as a temporary file and we've just collected a friendly display name for that sound. We want to accomplish two basic tasks:First, we want to add the custom sound to our data model. If information about our new custom sound is never added to the data model, then we'll never be able to render it to the Custom Sounds view on our MainPage.xaml. So, we'll create a new instance of the SoundData class and fill in the FilePath and Title properties appropriately. Next, we'll want to move that file from its temporary location to a permanent subfolder called /customAudio/ ... this is purely to keep all our custom sound files organized in one place. So, I add the following code to the FileNameCompleted() method:  I create a new instance of SoundData and fill in the Title and FilePath attributes. Notice that we'll be giving our custom sound a new name, but the contents of the file will remain the same. Just like when we originally recorded the custom sound, we get a reference to the IsolatedStorage area specifically for our app. We do this with a using statement to properly let go of unmanaged resources (like the Phone's storage). The very first time this code is executed, it may need to create the special folder where we're storing our custom audio files (line 76). Finally, we're moving the temporary file to the new permanent storage area and giving it a new name all in one fell swoop (line 78). Next, we're adding the new instance of the SoundData class to our CustomSounds.Items collection. At this moment, we should be able to return back to the MainPage.xaml and see the new custom sound appear in the list of Custom Sounds. However, what will happen when we close the application and it is complete removed from the Phone's memory? When that happens, the CustomSounds.Items collection will be removed from memory and the next time the app is run, it will have no memory of our custom sounds. We need a way to store our custom sounds data so that we can load it into our data model the next time the user runs our app. 4. Serialize and deserialize the CustomSounds SoundGroup into / out of JsonTo do this, we'll need to serialize our CustomSounds.Items collection into a data format. There are many data formats we could choose, but we'll pick a very popular, light-weight easy to use format called JSON. It is short for the JavaScript Object Notation. It will allow us to easily represent our collection as JavaScript objects. If we utilize a third-party open source library called Json.NET, we won't even have to think about the data's format ... much of that complexity will be hidden behind simple method calls.To begin, we'll open up the NuGet Package Manager (using the technique I demonstrated earlier ... right-click the References folder and choose the Manage NuGet Packages ... option. Search for: Json ... one of the top options should be Json.NET. Click the Install button next to the Json.NET package. It will take a few moments to install that package into your project. Click the Close button to continue. To verify that Json.NET was installed successfully, open up the References folder in the SoundBoard project and verify that Newtonsoft.Json appears there:  Back in the FileNameCompleted() method, the next step is to convert the CustomSounds.Items collection to Json, then store it to disk.We'll use the Newtonsoft.Json.JsonConvert class to perform the conversion ... you'll need to add the appropriate using statements to accommodate the JsonConvert class:  Now we're ready to fully implement the storage of the CustomSounds Json file to disk.  We use the JsonConvert.SerializeObject() method to serialize the CustomSounds object (and all it's children, etc.) into Json We'll use a special area of IsolatedStorage called IsolatedStorageSettings to save this object data. This is a simple way to save settings for your app. You can use the name / value pair pattern to save any settings you like for your app. So, in our case, we'll create a key and supply the value ... the value part is obviously the data -- the serialized Json data from the previous line of code. The key part will be a literal string that we'll create as a constant property in the SoundModel class definition. We'll need that key later to RETRIEVE the Json data back out of the IsolatedStorageSettings (we'll do that later in this lesson). We'll call the Save() method to actually save our new ApplicationSetting, the new name / value pair we created in the previous line of code. Before we forget, let's implement that CustomSoundKey ... in the SoundModel.cs file, I'll add the following line of code (line 19, below):  As you can see, this is nothing more than a constant string value. We want it to be constant because it should never change. It's simply a unique string we'll use as the means of getting back at the right ApplicationSetting in the IsolatedStorageSettings store.Next, we'll want to load our custom sounds into memory at the same time we instantiate all of the other SoundGroup objects ... in the SoundModel.cs file, in the LoadData() method:  In line 28 (above) we'll call a helper method, LoadCustomSounds(), to populate the CustomSounds property of the SoundModel class. Use the technique I demonstrated earlier to generate a method stub for this new method.In our new LoadCustomSounds() method, we'll attempt to retrieve the Json that contains the serialized Custom Sound data from the IsolatedStorageSettings: We perform a TryGetValue() method on the IsolatedStorageSettings.ApplicationSettings ... if the CustomSoundKey exists in IsolatedStorage, then it should return the value (i.e., the Json we stored previously) into the out parameter, "dataFromAppSettings". If not, t
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfIn this lesson we'll write the code required to record the custom sound. We'll employ the Coding4Fun Toolkit to help make this easier, but we'll still need to understand things like MemoryStreams and the phone's IsolatedStorage.Here's our game plan in this lesson:We'll modify the ToggleButton wiring up event handler methods to the Checked and Unchecked events. We'll use the MicrophoneRecord class in the Coding4Fun Toolkit's Audio namespace to begin and stop the recording process. When we stop recording, we'll need to temporarily save the sound stored in the phone's memory to a location on disk so it can be played back or saved permanently. We'll add a MediaElement control so we can enable playback of the sound. Manage the state of the Play sound button, turning it off and on depending on the recording action of the user. Let me just say that this is perhaps one of the most challenging lessons in this entire series because it deals with some slightly more advanced material. You should embrace this ... you only learn when you struggle, and challenging yourself with difficult concepts will help you grow faster. Be sure to not only watch this video, but also read the MSDN articles that I reference for more information. So put on your thinking cap and let's get started. 1. Modify the ToggleButton Control wiring up Event Handler MethodsEdit the XAML code on the RecordAudio.xaml page for the ToggleButton as follows:In lines 39 and 40 we wire up method handlers for the two states of the ToggleButton. 2. Create a private instance of the Coding4Fun.Toolkit.Audio.MicrophoneRecord classIn the RecordAudio.xaml.cs file, add the following line of code: We create a new private instance of the MicrophoneRecorder class, and use the hover-over-the-blue-dash technique to add a using statement for the Coding4Fun.Toolkit.Audio namespace.Now, we can start and stop the MicrophoneRecorder by adding code to the ToggleButton's Checked and Unchecked event handler methods:  3. Saving the sound data collected by the MicrophoneRecorder into a fileAs we're recording, the MicrophoneRecorder object is collecting the sound information in a buffer. A buffer is just a pocket of memory devoted to storing data. Buffers are typically used when there is a difference between the rate at which data is received and the rate at which it can be processed, or in the case that these rates are variable. So, it may take us 10 seconds to record a 10 second sound and during that time data is being added to the buffer. That said, the computer could process that data in a fraction of a second. The buffer is just a queue ... we can write the data at one rate of speed while reading it at another rate of speed. In programming, buffers are usually used between physical hardware and software, or when moving data from memory to disk and back, or data from memory to a network connection and back. I'm not a computer science guy, so I just think of a buffer as a bucket that you slowly collect things in until you're ready to work with the entire bucket at one time. So, I'm collecting shells on the beach and placing them into my bucket. Once I get a full bucket, I start processing them, deciding which to keep and which to throw away. I collect over a long period of time, then once I've filled my bucket, I process very quickly. That's how I think of a buffer.When we call the Stop() method, the MicrophoneRecord stops adding sound information, but is holding that data in memory, in a buffer and NOW we need to process the data in the buffer. In this case, when I use the term "process" what I mean is that I want to grab the sound data out of the buffer and place it as a WAV file into a temporary file.Once it's in a file sitting on my Phone's storage, I'll be able to hand that file over to a MediaElement and direct it to play that temporary WAV file. If the user wants to keep the file, I can re-name it and store it permanently.So, let's talk about storing files on a Windows Phone. The storage space on the phone is partitioned into isolated areas. Each app installed on the phone gets one of these isolated areas. I use the term "isolated" because one app can't look at the storage area of another app. This is for security ... one app can't rummage through your photos or notes or other secret data and upload it to a secret malicious server or corrupt it in some evil way.This isolated permanent storage area that's dedicated to your app is called IsolatedStorage. It's just a tidy way of keeping each app's data safe since each app is only able to write and read from its own storage area.So, back to the problem at hand ... the MicrophoneRecorder object has a bunch on data sitting in a buffer in memory, a MemoryStream object. My job is to save that data from the MemoryStream to a file—a temporary file—in IsolatedStorage. To accomplish this, I'll create a helper method that will take a MemoryStream as an input parameter and then in the body of the helper method, I'll create a new file in IsolatedStorage and then dump all the MemoryStream buffer data into that file.That's the plan, let's build it: As the screenshot indicates, the input parameter is of type MemoryStream and will need a using statement to reference System.IO.Next, we'll employ a different type of using statement:  In this context, the using statement will create a context for an instance of System.IO.IsolatedStorage.IsolatedStorageFile. Any code inside of the code block defined by the using statement will have access to the isoStore variable. Once the flow of execution leaves the closing curly brace, the isoStore variable will be disposed from memory properly.You use this using syntax when you want to work with classes that implement IDisposable ... typically these are managed types in the .NET Base Class Library (or in our case, the Windows Phone API) that access UNMANAGED resources. So the primary use of the IDisposable interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a MANAGED object when that object is no longer used. That said, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of UNMANAGED resources such as window handles, or open files and streams. The danger is that two or more processes (apps) attempt to access the same resources at the same time and cause an unrecoverable error condition. Types implementing IDisposable handle these scenarios correctly. For a more complete explanation of these topics:using Statement (C# Reference)https://msdn.microsoft.com/en-us/library/yh598w02.aspxIDisposable Interfacehttps://msdn.microsoft.com/en-us/library/system.idisposable.aspxThe IsolatedStorageFile class provides methods that help you manage the files and folder for use by your app. We use the GetUserStoreForApplication() to retrieve the IsolatedStorage area for just our app.Next, we'll grab the buffer and attempt to create a file in our IsolatedStorage area:  In line 69, I add a line of code that will retrieve values from the buffer (passed in to the helper method) and convert it to the format of a wav (audio) file. As you can see, the MemoryBuffer doesn't implement this method. Instead, we want to use an extension method from the Coding4Fun.Toolkit.Audio.Helpers namespace. So, in order to apply this extension method, we'll add another using statement at the top of our code file:  An extension method in .NET allows you to attach a method to any type. So, I could add some utilities to the int or string or, in this case, the System.IO.MemoryStream. The extension method allows you to work with the members of that type just like any public method could. For more information on extension methods, and how to create your own, check out:https://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspxNote: this is an advanced topic ... as long as you understand what they do and what purpose they serve, that's enough for now. Later you can learn how to create your own.Ok, so now we have the buffer in wav (audio) format, we just need to actually put it into a new file on the device's IsolatedStorage area:  (1) We create a temporary name for the wav file. We may discard this in the future (should the user hit the Record button again).(2) The CreateFile() method creates a file on the file system using the name we pass in (line 73, above), and gives us back a reference to that we can use to write to.(3) Now that we have an empty file to write to, we'll write the data stored in the bytes variable containing our sound. The Write() method's second and third parameters allows us to specify a portion of the sound data we want to write ... in this case, we'll write the entire file from the beginning (0) to the end (bytes.Length). 4. Add a MediaElement to play the new temporary fileIn the RecordAudio.xaml file, beneath the ContentPanel grid control, we'll add a MediaElement control, give it a name, and set AutoPlay to false:Back in the RecordAudio.xaml.cs, we'll programmatically set the source of our new MediaElement to our new temporarily sound file:Now we're ready to play the sound file ... we just need to wire-up the event handler for the Play button. 5. Handle the Play button's Click Event to Test the SoundIn the RecordAudio.xaml file, in the definition for the Button element with the content "Play", we'll add a Click event handler called "PlayAudioClick":Navigate to the new event handler and add the following line of code to call the Play() method of the MediaElement control:At this point we have it all wired up, but it's not pretty ... it's pretty fragile ... so we'll need to comb back through this and program defensively. We'll do that later in this lesson.For now, let's test our app. We've written a lot of code and, due to the nature of the functionality we've created, it wasn't possible to test it in small parts. We
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfNow that we can navigate to the new RecordAudio.xaml page, it's time to focus on the layout of this page. If you'll recall from our low-tech UI sketches, we envisioned a simple reel image that would rotate to indicate that the app was recording. There would be a button to start the recording process and a button to play back the sound. Finally, there would be an app bar to save the sound and give it a name. In this lesson, we'll get started by laying out the page and worry about the audio recording functionality and the animation later.So the game plan in this short lesson is pretty straight forward ...We'll make branding changes, binding to our LocalizedResources. We'll add the buttons and ellipse, and then add some shapes on the ellipse to make it look like an old-fashioned reel. We'll add an app bar like we learned how to do earlier.  1. Perform simple branding changesWe'll begin by modifying the text at the top of the app:We'll pull the app's name from our LocalResources.resx file through the familiar syntax we've used many times before. For now, I'll just hardcode the Text attribute as "record audio". That should produce the following results:  2. Perform basic layout of primary controlsI'll add the following XAML in the ContentPanel Grid: We'll use a StackPanel to stack the controls in a vertical fashion. We'll use a ToggleButton, which has two states: on and off. The idea is that we want to turn recording on and off. When the ToggleButton switches states, we'll want to handle the event that is raised to begin or stop the recording process. We'll create a Grid that we'll use to position the Ellipse. We set the color of the Ellipse to the built-in PhoneAccentBrush color, the primary tile color selected for the phone. We'll add one last button for playback of the last sound that was recorded. It should produce the following results:  The Ellipse control is not complete—we want it to look like an old reel to reel player. We can accomplish this by using several smaller shapes in XAML—a small Ellipse in the center, and small Rectangles aligned to different positions of the main outer Ellipse:  Hopefully most of the code is self explanatory. We use a series of Alignments and Margins to position the shapes on top of the main Ellipse.If correct, the results should look like this:  3. Add an App BarWe'll uncomment the lines of code provided by the file template to enable an app bar on the page. In the RecordAudio.xaml.cs file:  Hopefully none of this is new to you ... I've explained most of this code before, but specific to this app bar:Uncomment the call to BuildLocalizedApplicationBar(). Uncomment out the BuildLocalizedApplicationBar() method boilerplate. Create a new ApplicationBarIconButton, and set its IconUri property to the save.png file as well as set its text to the AppResources.resx entry AppBarSave that we created earlier in this series. Create and wire up a new event handler method for the Click event (see #7) ignoring the suggested name when I typed the += characters, instead preferring my own name, and then using the hover-over-the-blue-dash method to reveal the context menu option to generate a method stub. Add the recordAudioAppBar to the app bar. Make the application bar visible. This is the stubbed out event handler you created in step 4 (above). Running the app and navigating to this page will reveal the app bar with a small disk image titled "save".RecapTo recap, there are no big takeaways per se, just use the techniques we've learned before to implement the special layout for this page. The only new control you met was the ToggleButton which will toggle on or off as opposed to a typically button that can only be tapped / clicked.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfWhen someone clicks the microphone icon in our app bar, we want to take them to a new page where we can allow them to record a custom sound. To do this, we need to create a second page in our app, and then navigate from the MainPage.xaml to that new page. Navigation in Windows Phone Apps is similar to navigating from one web page to another. In this lesson, we'll learn about the Navigation API and, even though our needs are simple in this particular app, we'll find out the Navigation API capabilities with regards to how the Windows Phone 8 operating system re-hydrates apps shut down due to memory constraints.Our game plan in this lesson ...Revisit the Databound Project template to observe how it navigated from the main page to the details page. Discuss the classes required for navigation in the Windows Phone 8 API. Implement the code necessary to navigate from our main page to a new page that we'll use to record a custom sound.  1. Revisiting the Databound Project template to learn about navigationIf you'll recall a few lessons ago when we looked at the Databound Project Template, we saw how tapping one of the list items ... ... navigates to another page containing more details about the given item:  In addition to the MainPage.xaml, the project template also has a second page called DetailsPage.xaml:  In the MainPage.xaml.cs file, in the MainLongListSelector_SelectionChanged event handler method, we see the code required to enable this. Focus on lines 47-50:  The NavigationService class is used to simply navigate from one XAML page to another. However, it has a larger role in more complex scenarios. Since it is solely responsible for navigation between XAML pages, it also allows you to inspect the navigation history (called the "back stack"), remove entries from the back stack, and then observe the effect that these changes have on the navigation through the app.To learn about some of the advanced functionality of the NavigationService() class, check out this article on MSDN:https://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394012(v=vs.105).aspx However in our case, we merely need to navigate from the MainPage.xaml to a new page. We don't need to worry about alternate back page scenarios, passing values between the pages, or the like. Therefore, this other article on MSDN describes the process we'll use in general terms, in case you want to do a little additional research:https://msdn.microsoft.com/en-us/library/windowsphone/develop/ff626521(v=vs.105).aspx Most of the simple navigation scenario is accomplished using the the Navigate() method in the code example.Notice the Uri that is used as an input parameter to the Navigate() method. The Uri object represents a Uniform Resource Indicator, similar to a URL but has more utility and as more far reaching. The Uri has two basic parts—a string that represents a location, and a UriKind that should be used to interpret the location string.Let's start by parsing through the string ... you'll notice that it is part string literal, part dynamic value that retrieves its value from the current selected item in the LongListSelector. They are appended together with the plus + operator:"/DetailsPage.xaml?selectedItem=" + MainLongListSelector.SelectedItem as ItemViewModel).IDThe first part of the literal string should be obvious—it is the XAML page we want to navigate to. Everything after that—i.e., after the question mark ? character—is a query string. You've undoubtedly seen a query string before, even if you didn't know what it was called. A query string is a means of sending additional information along with the intended page to be loaded. I said you've undoubtedly seen this before because it is one of two or three primary ways of sending additional data between stateless web pages and is used ubiquitously on the World Wide Web.If you look at a search for the name "Clint Rutkas" on Bing.com, the navigation bar in your web browser will look like this:http://www.bing.com/search?q=clint+rutkas&go=&qs=n&form=QBLH&pq=clint+rutkas&sc=8-9&sp=-1&sk=It's simply a clever way of passing information from one web page that's intended to be interpreted and processed by another web page.In the code example we're examining, when someone taps an item in the LongListSelector we want to send the ID for the item that was selected from the MainPage.xaml to the DetailsPage.xaml ... the ? separates the page name from the query string portion of the URL. The query string is in the form of a name / value pair.For example:selectedItem=3... the selectedItem is the name of the pair, and everything after the equals character is the value of the pair.Two name / value pairs are separated by an & ampersand character. We'll see this used later in this series to send geo-positional latitude and longitude from one page to another ... it will look like this:?latitude=41.8986&longitude= 87.6230This is how you are able to pass multiple values in one string. Clever.The second constructor argument for the new Uri takes an enumeration of type UriKind. There are three possible values:UriKind.Relative UriKind.Absolute UriKind.RelativeOrAbsolute In regards to the differences between the first two, check out this page:https://msdn.microsoft.com/en-us/library/system.urikind(v=vs.95).aspx... which says the following:"Absolute URIs are characterized by a complete reference to the resource (example: http://www.contoso.com/index.html), while a relative Uri depends on a previously defined base URI (example: /index.html)."In our case, a relative Uri would be "relative to the project's structure". When we prefix the UriString with a forward-slash character / we're specifying the root of the project's deployment package. That should correspond with what we see in the Solution Explorer ... the DetailsPage.xaml is in the root of the project folder. When the project is deployed, those two .xaml files will both be in the root of the package like we saw when we opened up the PetSounds.xap file as a zipped file.But what about the UriKind.RelativeOrAbsolute? That's a bit trickier. The best I can figure out is that we're simply asking the runtime to figure it out for itself. It will attempt to clean up the UriString we provide and figure out where resources are. I think we could switch that to UriKind.Relative and it would work, too.Once the NavigationService loads the new page, the DetailsPage.xaml, an event called OnNavigatedTo() fires. Notice its code:  In line 31, the NavigationContext.QueryString.TryGetValue("selectedItem") will retrieve the value of the name / value pair in the query string as an out parameter if the parameter name exists. Next, that selectedItem value is used to load the correct item from the data model, and set it as the DataContext for the DetailsPage.xaml so that the various TextBlock controls can bind to it (line 35).Now that we have seen a full-fledged navigation example at work, we're better prepared to tackle this in our own project. 2. Create the RecordAudio.xaml PageLet's begin by creating that new page we want to navigate to: Make sure you're in the C# file templates section Select "Windows Phone Portrait Page" Rename to: RecordAudio.xaml Click the Add button Back in the MainPage.xaml page, we'll revisit the event handler method stub we created several lessons ago called RecordAudioClick():  3. Implement the code to navigate to the new pageI'll replace the exception (intended to be a reminder) with the following line of code: Hopefully, this version will be dramatically simplified when compared to the hairy example we saw earlier. We create a new Uri object with a simple address to our new RecordAudio.xaml page, and use the UriKind.RelativeOrAbsolute enum value.Now, let's test that line of code by running the app and clicking the microphone icon in the app bar:  ... if all goes well, we should see a default page template like so:  Great! We'll need to revisit this notion later in this series of lessons with a slightly more complex example in which we pass data between the pages. RecapTo recap, the big take away from this lesson is how to navigate between XAML pages using the NavigationService. We learned what a Uri object is, how to specify a page location and even pass parameters between pages, what the UriKind enumeration options mean, and so on.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfRecording a custom sound in our app would be difficult to code by hand. Fortunately, your friends at Coding4Fun, and Clint Rutkas specifically, have created a Toolkit for Windows Phone that hides the complexity behind easy to use programmatic interfaces. If you're not familiar with Coding4Fun, it's a Channel9 site that engages in geeky cool projects, not your standard business apps ... they usually use hardware like the Kinect as the interface for controlling things such as boxing robots and even a Ford Mustang that was heavily modified with Microsoft technology ... just to prove that it could be done.https://channel9.msdn.com/coding4funClint is usually in the center of these projects and he is the author and curator of the Coding4Fun Toolkit.By using this package in our project, we get some additional tools we can utilize in our apps such as a little "About This App" message box (the AboutPrompt) suited for Windows Phone development. In this lesson, I'll demonstrate how to install the Coding4Fun Toolkit package into our app using NuGet. Once we install it, we'll use it to implement the AboutPrompt.In this short lesson, our game plan is to:Use NuGet to install the Coding4Fun Toolkit package into our solution. Snoop around and see what it added. Add an AboutPrompt to our app. Update to series: Being sure we have the newest version of NuGet.With a fresh install of Visual Studio 2012, we’ll need to update NuGet to get some of the newer packages such as the Coding4Fun Toolkit.  It is a super easy process and can be done in a few clicks.Go to the Tools Menu –> Extensions and Updates Go to the Update Tab –> Visual Studio Gallery Click Update Restart Visual Studio1. Install the Coding4Fun PackageThere are many ways to get to the NuGet package manager ... this time we'll right-click on the References folder and select "Manage NuGet Packages ...": This will open up the Manage NuGet Packages Dialog: In the Search box, search for: "Coding4Fun". Click the Install button next to the "Coding4Fun Toolkit - Complete" package ... Clint split up the Coding4Fun toolkit into sub-packages so that developers can just pick and choose the parts they want in their project. However, for simplicity—and because we'll use a few different parts and want to familiarize ourselves with the package, we'll choose to install the Complete version. After a few moments, you'll see green checkmarks next to the packages that were installed: ... and you can click the Close button that in dialog to close it.Now, in the Solution Explorer, you can see new References that were added:  ... also, a new folder called Toolkit.Content and a ReadMe.Coding4Fun.Toolkit.txt file were added:  Opening the ReadMe.Coding4Fun.Toolkit.txt file, we can see versioning information (what changed) and migration notes:  2. Employing the AboutPromptWe'll take the simple step of adding an AboutPrompt to the app. When the user selects the "About" menu option, we want to display a popup:  We're missing a using statement, so use the hover-over-the-blue-dash-technique to add the appropriate using statement to the code file:  Once we've resolved the reference to the AboutPrompt class, we'll call it's Show() method. There are many overloaded versions of this method, but we'll pass in the following information ...  ... which produces the following results:  It's quick and simple and for this particular app, we probably need nothing more fancy.Leveraging open source (or even commercial) packages is a great way to add features quickly to your development projects. The whole .NET community on CodePlex is built on sharing packages, components, templates and so on to help each other quickly implement features. You can save yourself a lot of time during your career by spending a few hours exploring the work of others before going off and writing your own. Alternatively, use the search box on the NuGet Package Manager to find similar packages and evaluate the strengths and weaknesses of each one relative to the needs of your project. RecapTo recap, in this lesson we leveraged the Coding4Fun Toolkit to add one small feature now as well as one large feature later in this series. We learned how to add packages to our app using the NuGet Package Manager dialog, how to read the description of the package to learn more, and how packages can be subdivided to minimize unnecessary references and complexity in our projects.
Source Code: https://aka.ms/absbeginnerdevwp8 PDF Version: https://aka.ms/absbeginnerdevwp8pdfOur app works great as a simple SoundBoard, but we want to push the envelop and enable custom sounds—sounds that the user can record and re-use. This will require a few changes to our app ... in this lesson, we'll add an Application Bar with a Record button. When the user clicks it, we'll navigate the user to a new XAML page where they can record new custom sounds.You've probably seen an application bar before, even if you didn't realize what it's name was. Application bars appear at the bottom of the viewable area for your app and can contain a number of icons as well as an ellipsis which, when tapped, reveals text below the icon, and possibly a menu of additional options. We'll see it at work before the end of this lesson.Here's our game plan for this lesson:The project template already creates some boiler plate code for an application bar. We'll un-comment out their code and revise it to display an application bar with a record button and a menu option. We'll work with the AppResources.resx so that the text on our new application bar can be localized in the future. We'll clean up some unused files ... the old data model should go. We'll wire up and create event handler method stubs for the application bar button and menu option. In subsequent lessons, we'll flesh out the functionality in the event handler methods.  1. Enable the boilerplate BuildLocalizedApplicationBar() methodIn the MainPage.xaml.cs, the MainPage() constructor has a commented out line of code calling the BuildLocalizedApplicationBar(). I'll un-comment that line of code out: ... and then un-comment out the actual method further down on the code page:  By un-commenting out these lines of code, we've added a simple application bar to our app. 2. Modifying our Application Bar Button and TextObviously, we'll want to change the image that is referenced in line 67 (above) to reference the microphone.png file in the Assets\AppBar folder:  So, I'll make this change:  ... and I'll run the app. This reveals the app bar with the microphone icon and the ellipsis which, when tapped, reveals a menu option titled "Menu Option":  Below the microphone icon, the word "add" appears. Let's change both of these.First, the title of our method, "BuildLocalizedApplicationBar", suggests that this Application Bar retrieves it's textual values from the AppResources.resx, so let's open that file:  ... and make the following changes:  I add a property named AppBarAbout and set its value to About I add a property named AppBarRecord and set its value to Record I add a property to AppBarSave and set its value to Save Also, I remove any properties I no longer need, including:AppBarButtonText AppBarMenuItemText SampleProperty ... and I save this file.Next, I'll need to re-write some of the BuildLocalizedApplicationBar() to utilize the settings added in the AppResources.resx file:  I re-write the creation of the "Record" button I re-write the creation of the "About" menu option I add them both to the Application Bar  3. Removing the old data modelWhen I attempt to run the app, I see that I may have been too hasty in deleting the "SampleProperty" from the AppResources.resx:  I find that the source of the problem is code that I don't even use anymore ... i.e., the OLD data model code:  I can kill two birds with one stone by deleting the old data model classes. I select ItemViewModel.cs and MainViewModel.cs, right-click, select Delete from the context menu. That cleans up the code base removing unnecessary code and removes the errant reference to the nonexistent entry in the AppResources.resx:  One of my favorite authors says that you stay organized to stay productive. Keep your work area clean, like a sushi chef. Though I comment out code I don't think I'll need anymore, I also want to comb through the code once a day to keep the codebase pristine. When I open someone else's code and I look at it, I automatically assume it's all being used. Sometimes, however, there are classes or methods no longer called. This adds friction and confusion. When I'm not recording videos and actually writing code, I rely on a third-party tool called ReSharper ... it will analyze your code and find unused classes and methods, it can locate duplicate code and recommend changes and a thousand other improvements to your code. I highly recommend it.At any rate, when we run the app this time we can see that the app bar looks has the text we would expect:  4. Responding to the Click event of the App Bar's Record buttonFinally in this lesson, we want to wire up the click event handler methods to our new button and menu items: I add line 69 which, as we learned in the lesson on Events, will add the RecordAudioClick method in its list of methods that will be triggered by the click event of the Record button. To create a method stub, use the technique we learned in the Event lesson—hover your mouse cursor over the blue dash under the letter R in RecordAudioClick to reveal a menu, and choose the "Generate method stub ..." menu option:  This will create a method stub for the event handler, complete with a reminder that the method is not yet implemented by throwing an exception:  We'll repeat this process for the "about" menu option. In line 75 (below) I associate a method event handler called AboutClick to the click event of the menu option:  ... and I use the technique described earlier to create a method stub for RecordAudioClick() (lines 86 through 89). RecapTo recap, the big take away is how to create a new application bar, application bar icon, and application bar menu option. We used templated code and the AppResources.resx and wired up event handler method stubs, which we'll fully implement out in the coming lessons.
loading
Comments