<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Peter Torr's Blog</title><link>http://blogs.msdn.com/b/ptorr/</link><description>Posts about Windows Phone 7 application development with Silverlight. And other stuff.</description><dc:language>en-US</dc:language><generator>Telligent Community 5.6.583.19199 (Build: 5.6.583.19199)</generator><item><title>Back means back. Not forwards, not sideways, but back</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/10/06/back-means-back-not-forwards-not-sideways-but-back.aspx</link><pubDate>Thu, 06 Oct 2011 20:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10221280</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10221280</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10221280</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/10/06/back-means-back-not-forwards-not-sideways-but-back.aspx#comments</comments><description>&lt;p&gt;Windows Phone Mango introduces a lot of great new features for developers: &lt;a href="http://msdn.microsoft.com/en-us/library/hh202946(VS.92).aspx" target="_blank"&gt;alarms &amp;amp; reminders&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/hh202979(VS.92).aspx" target="_blank"&gt;pinned secondary tiles&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ff402558(VS.92).aspx" target="_blank"&gt;deep-linked toasts&lt;/a&gt;, and &lt;a href="http://msdn.microsoft.com/en-us/library/hh202957(VS.92).aspx" target="_blank"&gt;AppConnect&lt;/a&gt; to name just a few. One thing that Mango &lt;em&gt;hasn&amp;rsquo;t &lt;/em&gt;changed, however, is &lt;a href="http://msdn.microsoft.com/en-us/library/ff941091(VS.92).aspx" target="_blank"&gt;the overall navigation structure&lt;/a&gt; of Windows Phone&amp;rsquo;s &amp;ldquo;Metro&amp;rdquo; design and the purpose of the hardware back button. I&amp;rsquo;ve previously blogged about the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx" target="_blank"&gt;concept of places&lt;/a&gt; and the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/02/23/this-is-not-the-exit-you-are-looking-for.aspx" target="_blank"&gt;tyranny of exit buttons&lt;/a&gt;, but with the changes in Mango I wanted to provide a refresher and also update with some new guidance for the new scenarios.&lt;/p&gt;
&lt;p&gt;You may find this post quite repetitive. That is deliberate; I really want to illustrate the fundamental concepts on the phone, to show the patterns already established by the built-in experiences, and to drive home the need for consistency in marketplace applications in order to maintain a high degree of user satisfaction.&lt;/p&gt;
&lt;p&gt;The most critical point to remember is that &amp;ldquo;back means back&amp;rdquo; &amp;ndash; it is used throughout the phone to do one of two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dismiss transient UI such as alert dialogs, popup menus, pick lists, driving directions, and the SIP&lt;/li&gt;
&lt;li&gt;Return to the previous page (place)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(The astute reader might note that a long-press of the back button is also used to bring up the task switching UI, which is a variation on returning to a previous place. It's also used in games to bring up a 'pause' menu, but games are always the exception that prove the rule).&lt;/p&gt;
&lt;p&gt;The back button is never used to move forwards to a new page.&lt;/p&gt;
&lt;p&gt;The back button is never used to substantially change the content of the current page.&lt;/p&gt;
&lt;p&gt;This principle has not changed in Mango. It has not changed with alarms &amp;amp; reminders. It has not changed with secondary tiles or deep-linked toasts. It has not changed with AppConnect. &lt;strong&gt;It has not changed at all&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Follow our lead&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s look at some examples of built-in phone features and how they relate to the new Mango APIs.&lt;/p&gt;
&lt;h3&gt;Reminders&lt;/h3&gt;
&lt;p&gt;If you have an appointment in the built-in Windows Phone calendar and it is set to show a reminder, the phone will popup a reminder at the appropriate time. Tapping on the text of the reminder takes you into that appointment, as you would expect. From that appointment, hitting the Back button takes you back to whatever you were doing before.&lt;/p&gt;
&lt;p&gt;It does not take you to the calendar view. It takes you back to what you were doing.&lt;/p&gt;
&lt;p&gt;Reminders from marketplace applications should behave exactly the same way. Tapping on the text of the reminder should deep-link into the application to show detailed information, and the Back key should always exit the application and return the user to what they were doing.&lt;/p&gt;
&lt;h3&gt;Secondary Tiles&lt;/h3&gt;
&lt;p&gt;Many of the built-in applications allow you to pin secondary tiles. The People hub lets you pin individual people or groups; Zune lets you pin albums, playlists, and artists; maps lets you pin locations; and so on. When you tap on the pinned item, it takes you directly to the contact, album, location, etc. and when you hit the Back button you return to the Start menu.&lt;/p&gt;
&lt;p&gt;It does not take you to the main hub or application. It takes you back to the Start menu.&lt;/p&gt;
&lt;p&gt;Pinned secondary tiles for marketplace applications should behave exactly the same way. Tapping on a tile should deep-link directly into the content that the user pinned, and the Back key should always exit the application and return to Start.&lt;/p&gt;
&lt;h3&gt;Toasts&lt;/h3&gt;
&lt;p&gt;The built-in messaging application shows toasts when you receive an IM or SMS. Tapping on the toast takes you to the appropriate conversation where you can read and optionally reply. From the conversation, hitting the Back button takes you back to whatever you were doing before.&lt;/p&gt;
&lt;p&gt;It does not take you to the all-conversations list. It takes you back to what you were doing.&lt;/p&gt;
&lt;p&gt;Toasts for marketplace applications - whether they come from Push notifications or from background agents &amp;ndash; should behave exactly the same way. Tapping on a toast should deep-link directly to the appropriate application context, and the Back key should always exit the application and return to what the user was previously doing.&lt;/p&gt;
&lt;h3&gt;App-to-app links&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s no direct analog of AppConnect for built-in experiences, but there are cases where one application will link to another, such as when you receive an e-mail with an attached Office document or picture &amp;ndash; opening the attachment launches the associated application to display the content. From that application, hitting the Back button takes you back to the original application (in this example, e-mail).&lt;/p&gt;
&lt;p&gt;It does not take you to the Office hub or the Pictures hub. It takes you back to what you were doing&lt;/p&gt;
&lt;p&gt;AppConnect-enabled applications should behave the same way. If the user searches for a movie in Bing and taps on one of the AppConnect results, that application should show content specific to the movie (show times, reviews, streaming options, etc.). Hitting the back key from that page should exit the application and return to the Bing results.&lt;/p&gt;
&lt;h2&gt;Allowing further exploration&lt;/h2&gt;
&lt;p&gt;The previous section discussed how the built-in experiences deal with the back button to enable users to quickly &amp;ldquo;glance and go&amp;rdquo; at information and then easily and &lt;span style="text-decoration: underline;"&gt;consistently&lt;/span&gt; return to their previous activity with the Back button. But what if the user doesn&amp;rsquo;t want to return to their previous activity? What if they want to stay within the application and continue exploring or using other features?&lt;/p&gt;
&lt;p&gt;Using the built-in experiences again as an example, if you pin a group to Start, after tapping on it you can take additional actions such as viewing an individual person&amp;rsquo;s profile, sending them an e-mail, browsing their pictures, and so on. No matter what other activities you perform, the sequence of pages the user sees as they hit the Back key is predictable and eventually lands them back at the Start menu without any surprises.&lt;/p&gt;
&lt;p&gt;Marketplace applications can do exactly the same thing. If you deep-link into an item from any of the extension points mentioned above, it is fine for you to allow further actions to be taken from that point on. But these further explorations must be forward navigations, never backwards. You can use UI affordances such as hyperlinks, buttons, thumbnail images, or other entry points that the user will naturally perceive as forward navigations deeper into the application. And then when they are done and they want to return to what they were doing, they can use the Back button.&lt;/p&gt;
&lt;p&gt;As noted above, none of the built-in applications provide a way to get from a deep-linked item back to its &amp;ldquo;container&amp;rdquo; hub or application. If you pin a group to Start and tap on it, Back takes you to Start, not to the People hub. In fact, there&amp;rsquo;s no way to navigate from a pinned group to the all-people list, even via forward navigation. All the actions you can take within the pinned group are scoped to the context of that particular group. The same is true of pinned Zune content (albums, artists, etc.) but pinned map locations are a little different since once you are viewing the map you are free to perform additional searches (note, however, that Back will always take you to the initial pinned location).&lt;/p&gt;
&lt;p&gt;Simplifying applications and their navigation structure is a design pattern that &lt;a href="http://msdn.microsoft.com/en-us/library/hh202903(VS.92).aspx" target="_blank"&gt;we recommend all applications follow&lt;/a&gt;, regardless of their high-level design. Keeping the application structure simple and scoping down the actions the user can take avoids confusion and having the user go off &amp;ldquo;into the weeds.&amp;rdquo; Nevertheless, sometimes users really do want to move from a single deep-linked item to the full application experience. An example might be a shopping application where the user has both the main application tile and a &amp;ldquo;wish list&amp;rdquo; tile pinned to the Start menu. Tapping the main tile launches the application into its normal browse / search UX, but tapping on the wish list tile lands them directly at their wish list. From here, the user can quickly see the items on their wish list, dive into product details to review customer ratings and price comparisons, and perhaps delete items that are no longer desired. All this can be done using the techniques described above to facilitate seamless, consistent, in-and-out behaviour for the wish list. Tapping the tile launches the wish list, and hitting Back returns to Start. Tapping the tile and drilling into an item shows its details, hitting Back once returns you to the entire list, and hitting Back again returns you to Start.&lt;/p&gt;
&lt;p&gt;But in this scenario there are some more complicated things the user might want to do though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Purchase the items in their wish-list by going through a checkout procedure&lt;/li&gt;
&lt;li&gt;Add new items to their wish list by browsing / searching the catalog&lt;/li&gt;
&lt;li&gt;Engage in free-form discovery, purchase a one-off item, create a new type of list, or perform other actions not directly related to the wish-list&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Completing a task&lt;/h3&gt;
&lt;p&gt;In the first case, the actions are still well-scoped to the original item that was pinned to Start. There might be an AppBar button, for example, that allows the user to purchase the items. The purchase experience may require several steps (especially if the user doesn&amp;rsquo;t already have a credit card or billing address on-file) and each of those steps might be implemented as a page in your application. While the user is performing the checkout operation, it makes sense for the Back button to return to the previous step. For example, if the user went from the wish list page to the billing address page to the credit card page, pressing Back would return them to the billing address page, then the wish list, then to Start.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/2330.checkout_5F00_process_5F00_2.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="checkout_process" border="0" alt="checkout_process" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/3414.checkout_5F00_process_5F00_thumb.jpg" width="640" height="258" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once the user has completed the entire transaction, it doesn&amp;rsquo;t make sense for the Back key to traverse the (now stale) sub-steps of the purchasing flow - they can&amp;rsquo;t change their address or credit card number, for example - so those &amp;lsquo;orphaned&amp;rsquo; pages &lt;a href="http://msdn.microsoft.com/en-us/library/hh202868(VS.92).aspx" target="_blank"&gt;can be removed from the back stack&lt;/a&gt;. So if the user is presented with the confirmation page, pressing the Back button would return them to the (now empty) wish list, ready for them to add more items or return to Start by hitting Back again.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/5141.checkout_5F00_confirm_5F00_4.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="checkout_confirm" border="0" alt="checkout_confirm" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/5164.checkout_5F00_confirm_5F00_thumb_5F00_1.jpg" width="640" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Constrained exploration related to a task&lt;/h3&gt;
&lt;p&gt;In the second case, where the user wants to add more things to their wish list, there are a couple of options you might take. The first is very similar to the above approach; instead of the billing / credit / done sequence, you might have a search / results / details sequence, where once the user reaches the details page and hits &amp;ldquo;add to wishlist&amp;rdquo; the application automatically navigates back to the (now longer) wishlist, clearing all the items in the process. In this case, Back would exit the application:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/6708.add_5F00_auto_5F00_return_5F00_4.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="add_auto_return" border="0" alt="add_auto_return" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/0044.add_5F00_auto_5F00_return_5F00_thumb_5F00_1.jpg" width="640" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another solution would be the same search / results / details sequence, but after the user hits &amp;ldquo;add to wishlist&amp;rdquo; the app merely shows a confirmation that the item has been added, leaving the user to return to the search results or search pane for further exploration:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/4174.add_5F00_manual_5F00_return_5F00_2.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="add_manual_return" border="0" alt="add_manual_return" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/0602.add_5F00_manual_5F00_return_5F00_thumb.jpg" width="640" height="204" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Either of these approaches should be OK, since it is clear to the user that they have either completed a task (in the first case, similar to the purchase flow) or are still free to explore (in the second case). What&amp;rsquo;s important is that you don&amp;rsquo;t allow the user to go off &amp;ldquo;into the weeds&amp;rdquo; in such an experience so that they forget where they came from. For example, in the details page of the item above there are no options to find related items or to purchase it directly; the activity is well-scoped to just adding things to the list. (If this page was implemented using the same details page that was used for every-day browsing, you would dynamically remove these elements when in the context of the add-to-wishlist sequence). A concrete example here with a built-in experience is the photo viewer. If you launch the Photos hub and open up an image, the AppBar menu contains all sorts of commands to share, delete, save to favourites, and so on. But if you open a file attachment from an e-mail, there are only two options available to you: save and set as wallpaper. The user is prevented from getting too far off-track from their original task of reading e-mail.&lt;/p&gt;
&lt;h3&gt;Unconstrained exploration&lt;/h3&gt;
&lt;p&gt;In the third case, the user decides (for whatever reason) that they want to break out of the context for which they launched the application and just start using your application as if they had launched it from the primary tile. As noted above, none of the built-in applications provide such a feature, so you should think long and hard about whether it really makes sense for your application or whether it would do more harm than good. If you think it will be a common case that the user wants to transition from a deep-linked item (secondary tile, incoming toast, etc.) to an unrelated portion of the application, consider the possibility that you&amp;rsquo;re exposing the wrong types of things as deep links. Just because the feature is there, doesn&amp;rsquo;t mean you have to use it.&lt;/p&gt;
&lt;p&gt;Nevertheless, there will be legitimate cases where the user wants to go from a deep-linked item into the broader context of the application. I gave one example of this in my &lt;a href="http://channel9.msdn.com/Events/MIX/MIX11/DVC11" target="_blank"&gt;Multitasking talk at MIX 11&lt;/a&gt;, where I demonstrated &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx" target="_blank"&gt;a simple &amp;ldquo;to-do&amp;rdquo; application&lt;/a&gt; that allows the user to remind themselves of things they need to do. In this instance, it is not unreasonable to expect that once the user is reminded to complete task A, they &lt;em&gt;might &lt;/em&gt;want to see what tasks B, C, and D are in order to appropriately plan their execution. Note that the rules above about the behaviour of Back still apply. If the user taps on the reminder and sees the detailed page for the to-do item, pressing Back will exit the application and return them to what they were doing.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/7888.reminder_5F00_back_5F00_2.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="reminder_back" border="0" alt="reminder_back" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/0535.reminder_5F00_back_5F00_thumb.jpg" width="240" height="197" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But if they want to see what other items are still left to do, the application provides them with an additional &amp;ldquo;home&amp;rdquo; command that essentially re-sets the application by navigating them to the home view and clearing the back stack.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/8372.reminder_5F00_home_5F00_2.jpg"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="reminder_home" border="0" alt="reminder_home" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/2526.reminder_5F00_home_5F00_thumb.jpg" width="640" height="253" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this case, pressing Back exits the application rather than taking them back to the original deep-linked item, which is indeed an exception to the rule that &amp;ldquo;back always goes back&amp;rdquo; but it is a very specific one for which we can add a third case:&lt;/p&gt;
&lt;ol&gt;
&lt;li value="3"&gt;If the user explicitly navigates &amp;ldquo;home&amp;rdquo; (using some clear and obvious UI affordance) then the back stack is cleared and Back immediately exits the application&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Do what&amp;rsquo;s right for the user&lt;/h2&gt;
&lt;p&gt;All of this guidance really boils down to one simple thing, which is letting the user interact with your application in a manner that is &lt;span style="text-decoration: underline;"&gt;most natural for them&lt;/span&gt;. To a lesser degree, it&amp;rsquo;s about respecting your users and trusting them to make the right decisions as they navigate your application and the phone in general. If they popped in to the app to quickly check up on something, the most obvious and consistent mechanism for them to get out again is to hit Back. If they want to drill in deeper, the most obvious and consistent mechanism for them to do that is through forward navigation.&lt;/p&gt;
&lt;p&gt;Windows Phone has a different overall user experience than iOS or Android or Symbian or BlackBerry (or any other OS for that matter). The way a user interacts with your application on another platform may not translate well to how they would interact with your application on Windows Phone. And whilst it might seem logical to say &amp;ldquo;users who move from other OSes to Windows Phone will be confused if apps work differently&amp;rdquo;, remember that the &lt;strong&gt;vast majority &lt;/strong&gt;of smart phone purchases in the future will come not from people switching from one OS to another, but from people who have never owned a smartphone before and, in many cases, have never owned a PC before either. These are your future customers and they have no pre-conceived notions of how apps &amp;ldquo;should&amp;rdquo; or &amp;ldquo;should not&amp;rdquo; work; they will simply notice which apps do or do not work well on the phone they choose to buy. In other words, familiarity with the behaviour of other smartphone OSes is not a good excuse for building poor Windows Phone experiences.&lt;/p&gt;
&lt;h2&gt;Some implementation tips&lt;/h2&gt;
&lt;p&gt;Guidance itself isn&amp;rsquo;t worth much when you&amp;rsquo;re in the trenches pounding out code, so how about some examples? Luckily for me, I&amp;rsquo;ve already published code that is applicable to this scenarios before, and our documentation already covers these topics with conceptual articles and samples. &lt;a href="http://marketplace.xbox.com/en-US/Product/Gears-of-War-3/66acd000-77fe-1000-9115-d8024d5308ab" target="_blank"&gt;Yay for not having to write more sample code! :-)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In particular, the aforementioned &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx" target="_blank"&gt;alarms and reminders post&lt;/a&gt; includes code to conditionally display a &amp;ldquo;home&amp;rdquo; button on a deep-linked page and how to clear the backstack such that the Back key works as the user would expect. This technique works for reminders, deep-linked toasts, and secondary tiles. There is also a &lt;a href="http://msdn.microsoft.com/en-us/library/hh394012(VS.92).aspx" target="_blank"&gt;complete &amp;ldquo;how-to&amp;rdquo; article on MSDN&lt;/a&gt; that explains this topic in detail, and the new Mango backstack APIs should be able to replace any use of the old &lt;a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2010/12/13/solving-circular-navigation-in-windows-phone-silverlight-applications.aspx" target="_blank"&gt;non-linear navigation service&lt;/a&gt; in existing Windows Phone applications.&lt;/p&gt;
&lt;p&gt;Another earlier post on &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/28/redirecting-an-initial-navigation.aspx" target="_blank"&gt;redirecting your first navigation&lt;/a&gt; might be helpful for cases where your application is launched with a set of parameters, such as from AppConnect. By adding a &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.navigation.urimapper(VS.95).aspx" target="_blank"&gt;UriMapper&lt;/a&gt; to your application and pattern-matching on the types of parameters that will be sent, you can bypass any interstitial screens and navigate directly to the right content in your application. There&amp;rsquo;s a full sample project included in &lt;a href="http://msdn.microsoft.com/en-us/library/hh202957(VS.92).aspx" target="_blank"&gt;the documentation page&lt;/a&gt; for AppConnect that shows exactly how to do this.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10221280" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Pages/">Pages</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/mango/">mango</category></item><item><title>BUILD 2011 demos</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/09/17/build-2011-demos.aspx</link><pubDate>Sun, 18 Sep 2011 05:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10213059</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10213059</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10213059</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/09/17/build-2011-demos.aspx#comments</comments><description>&lt;p&gt;&lt;span style="color: #0000ff;"&gt;[Update 9/21]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Just got back from //BUILD in Anaheim, and it was a great conference to be at. I presented "Multitasking in Windows Phone" for what seemed like the 100th time, and the slides + video are up on &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/APP-823T" target="_blank"&gt;channel 9&lt;/a&gt;&amp;nbsp;&lt;span style="color: #0000ff;"&gt;but unfortunately the video did not record the slides / demos until about 25 minutes into the video. I've asked to see if they can fix it but I am not hopeful. Sorry for those of you that can't see what's going on :-(&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Below I've attached the sample code I used in the demos - basically the same as other content I've posted on the blog, so no new commentary required.&lt;/p&gt;
&lt;p&gt;P.S. Thanks to &lt;a href="http://twitter.com/#!/gcaughey"&gt;Ginny&lt;/a&gt; who - for some strange reason :-) - seems to come to all my talks, no matter how repetitive that must be. You must know them all by heart now. Thanks for the support, I appreciate it!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10213059" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-21-30-59/build2011demos.zip" length="172896" type="application/zip" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/build/">build</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/mango/">mango</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/multitasking/">multitasking</category></item><item><title>More Knowledge Chamber videos on Channel 9</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/08/22/more-knowledge-chamber-videos-on-channel-9.aspx</link><pubDate>Mon, 22 Aug 2011 22:05:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10198714</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10198714</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10198714</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/08/22/more-knowledge-chamber-videos-on-channel-9.aspx#comments</comments><description>&lt;p&gt;In addition to the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/08/04/multitasking-video-on-the-knowledge-chamber.aspx"&gt;multitasking video I did the other week&lt;/a&gt;, several other Windows Phone folks have been doing videos, too. A current list (I am sure it will grow):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sean McKenna discusses &lt;a href="http://channel9.msdn.com/Shows/The+Knowledge+Chamber/Sean-McKenna-and-Windows-Phone-Mango-Database-Support"&gt;database support in Mango&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Thomas Fennel discusses &lt;a href="http://channel9.msdn.com/Shows/The+Knowledge+Chamber/Thomas-Fennel-and-Windows-Phone-Mangos-Push-Notifications-and-Live-Tile-Support"&gt;push notifications and live tiles in Mango&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can see more Knowledge Chamber videos (including ones for other technologies such as Silverlight, WCF, or Azure) &lt;a href="http://channel9.msdn.com/Shows/The+Knowledge+Chamber"&gt;here&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10198714" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>Multitasking video on The Knowledge Chamber</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/08/04/multitasking-video-on-the-knowledge-chamber.aspx</link><pubDate>Fri, 05 Aug 2011 04:55:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10193022</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10193022</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10193022</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/08/04/multitasking-video-on-the-knowledge-chamber.aspx#comments</comments><description>&lt;p&gt;If you already follow my blog, you probably know everything you need to know about Mango's multitasking support... but just in case you don't, you can check out a video I did with &lt;a href="http://channel9.msdn.com/Niners/Robert%20Hess"&gt;Robert Hess&lt;/a&gt; over at Channel 9.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://channel9.msdn.com/Shows/The+Knowledge+Chamber/Peter-Torr-and-Application-Multi-Tasking-on-Windows-Phone-Mango"&gt;http://channel9.msdn.com/Shows/The+Knowledge+Chamber/Peter-Torr-and-Application-Multi-Tasking-on-Windows-Phone-Mango&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks Robert!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10193022" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>Background Agents - Part 3 of 3</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-3-of-3.aspx</link><pubDate>Wed, 13 Jul 2011 03:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10185874</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10185874</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10185874</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-3-of-3.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;Part 1&lt;/a&gt; we looked at a simple app to get tweets from Twitter, and in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;Part 2&lt;/a&gt; we looked at the &lt;strong&gt;AsyncWorkloadHelper &lt;/strong&gt;library. In this final part, we'll look at a couple of the other helper libraries in the project that you might find useful. As before, the code can be found at the end of &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;Part 1&lt;/a&gt;. This post will hopefully be the shortest of the three since I am tired and I want to post this stuff already! :-)&lt;/p&gt;
&lt;h1&gt;The TwitterLibrary library&lt;/h1&gt;
&lt;p&gt;The first helper library we'll discuss is &lt;strong&gt;TwitterAccess&lt;/strong&gt;. I'm sure there are a million twitter libraries out there, and the world probably needs a million-plus-one-th library like it needs a hole in the head, but whatevz. I wanted to code one up myself! This library is basic and supports simple unauthenticated searches on Twitter for search terms. The API looks like this, and I won't bother explaining how it works (hint, look &lt;a href="http://msdn.microsoft.com/en-us/library/bb387098.aspx" target="_blank"&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/2330.image_5F00_217213B6.png" width="468" height="368" /&gt;&lt;/p&gt;
&lt;p&gt;An example of using the library to get a tweet can be seen in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;Part 2&lt;/a&gt; (or you could just read the code ;-) ).&lt;/p&gt;
&lt;p&gt;Oh all right, stop twisting my arm already. Here's a simple example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Asynchronously loads the tweets with the given search term&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"searchTerm"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The search term&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; LoadTweetsWithSearchTermAsync(&lt;span style="color: blue;"&gt;string&lt;/span&gt; searchTerm)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;TwitterHelper&lt;/span&gt;.GetAllTweets(searchTerm, tweets =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Tweet&lt;/span&gt;&amp;gt; temp = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Tweet&lt;/span&gt;&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; tweet &lt;span style="color: blue;"&gt;in&lt;/span&gt; tweets)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; temp.Add(tweet);&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.BeginInvoke(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;delegate&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Items = temp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nothing worth explaining here. Next!&lt;/p&gt;
&lt;h1&gt;The ShellUiHelpers library&lt;/h1&gt;
&lt;p&gt;This one's a bit more interesting; it has a simple helper and a more complex helper.&lt;/p&gt;
&lt;p&gt;The simple helper is &lt;strong&gt;ToastHelper&lt;/strong&gt;, a thin wrapper around the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltoast(VS.92).aspx" target="_blank"&gt;ShellToast&lt;/a&gt; API that lets you pop toasts for the user. The interesting thing that it does is supress toasts if the user is asleep (or, more accurately, &lt;em&gt;if the current system time is a time when we assume the user might be asleep&lt;/em&gt;). Nothing fancy but it helps with the &lt;a href="http://en.wikipedia.org/wiki/Wife_Acceptance_Factor" target="_blank"&gt;Spousal Approval Factor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The more complex helper is &lt;strong&gt;TileHelper&lt;/strong&gt;, which is a more complex wrapper around the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltile(VS.92).aspx" target="_blank"&gt;ShellTile&lt;/a&gt; APIs that can composite images for the front and back images of a tile. Given a call such as this, it performs a bunch of work on your behalf:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: #2b91af;"&gt;TileHelper&lt;/span&gt;.UpdateTile(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ExtendedTileData&lt;/span&gt;&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FrontText = &lt;span style="color: #a31515;"&gt;"latest tweet"&lt;/span&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FrontTitle = TweetSearchTerm,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackText = tweet.TweetText,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackTitle = tweet.AuthorAlias,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackImage = tweet.AvatarUri,&lt;br /&gt;&amp;nbsp; });&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, it checks if you are calling on the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher(VS.95).aspx" target="_blank"&gt;Dispatcher thread&lt;/a&gt; or not; you can't do this because of the blocking nature of the API (basically, &lt;strong&gt;UpdateTile &lt;/strong&gt;acts as a synchronous operation, but it dispatches work to the UI thread in order to compose the bitmaps. If you were on the UI thread already, you would block waiting for the UI operation, but it is waiting to be dispatched on the same thread... so you have a deadlock).&lt;/p&gt;
&lt;p&gt;Next, it uses the &lt;strong&gt;AsyncWorkHelper &lt;/strong&gt;APIs we discussed in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;Part 2&lt;/a&gt; to call two methods in parallel, &lt;strong&gt;GetBackgroundImage &lt;/strong&gt;and &lt;strong&gt;GetBackBackgroundImage&lt;/strong&gt;. These two methods take the metadata from the &lt;strong&gt;ExtendedTileData &lt;/strong&gt;class and compose them into two bitmaps, which are then saved as JPEGs and used for the tile backgrounds.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GetBackgroundImage &lt;/strong&gt;gets the "front" background image. Because the default tile template doesn't support text on the front of the tile (just a small &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltiledata.title(VS.92).aspx" target="_blank"&gt;Title&lt;/a&gt;), this method composes the &lt;strong&gt;background.png &lt;/strong&gt;found in the application's XAP (the default tile image created in a new project) with a rendered text string (the &lt;strong&gt;FrontText &lt;/strong&gt;property, above). It fades out the background a bit to make the text more readable, but you can change this by updating the &lt;strong&gt;FRONT_IMAGE_OPACITY &lt;/strong&gt;constant. The code uses a shared helper function to compose the image:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Composes a simple tile image and writes it to disk&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"background"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The background image&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"opacity"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;Desired opacity of the background image&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"text"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;Optional text to render into the image&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"baseFileName"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The base filename to use (no directory or extension)&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The actual full path to the file as written to disk&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;string&lt;/span&gt; ComposeTileAndWriteToDisk(&lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt; background, &lt;span style="color: blue;"&gt;double&lt;/span&gt; opacity, &lt;span style="color: blue;"&gt;string&lt;/span&gt; text, &lt;span style="color: blue;"&gt;string&lt;/span&gt; baseFileName)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Create a container of the correct size&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Grid&lt;/span&gt; container = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Grid&lt;/span&gt;();&lt;br /&gt;&amp;nbsp; container.Width = TILE_WIDTH;&lt;br /&gt;&amp;nbsp; container.Height = TILE_HEIGHT;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Add the text, if necessary&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;String&lt;/span&gt;.IsNullOrWhiteSpace(text) != &lt;span style="color: blue;"&gt;true&lt;/span&gt;)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; container.Children.Add(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;TextBlock&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Text = text,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TextWrapping = &lt;span style="color: #2b91af;"&gt;TextWrapping&lt;/span&gt;.Wrap,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Foreground = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;SolidColorBrush&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;Colors&lt;/span&gt;.White),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// The font size, line height, and margin have all been chosen to match the shell's rendering of text on tiles&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FontSize = 30,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LineHeight = 32,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LineStackingStrategy = &lt;span style="color: #2b91af;"&gt;LineStackingStrategy&lt;/span&gt;.BlockLineHeight,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Margin = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Thickness&lt;/span&gt;(12, 10, 8, 34)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Add the background&lt;/span&gt;&lt;br /&gt;&amp;nbsp; container.Background = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ImageBrush&lt;/span&gt;&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ImageSource = background,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Opacity = opacity,&lt;br /&gt;&amp;nbsp; };&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Force the container to render itself&lt;/span&gt;&lt;br /&gt;&amp;nbsp; container.Arrange(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Rect&lt;/span&gt;(0, 0, TILE_WIDTH, TILE_HEIGHT));&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Write the image to disk and return the filename&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; WriteShellTileUIElementToDisk(container, baseFileName);&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This code is pretty straight-forward; basically it creates a 173 x 173 pixel Grid, adds the text (if any) to it as a child element, then sets the background to the supplied image. Trial and error led to the values you see above for the text size and margins.&amp;nbsp; It then renders the image to disk using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.extensions.savejpeg(VS.92).aspx" target="_blank"&gt;SaveJpeg&lt;/a&gt; extension method (via the &lt;strong&gt;WriteShellTileUIElementToDisk &lt;/strong&gt;helper) and returns the full path to the rendered file. Note that for shell tile background images, the files must be saved in the &lt;strong&gt;/shared/shellcontent/&lt;/strong&gt; folder of IsoStore, which is set as the constant &lt;strong&gt;SHARED_IMAGE_PATH &lt;/strong&gt;in the code.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;GetBackBackgroundImage&lt;/strong&gt; method does something similar, but instead of using the &lt;strong&gt;background.png&lt;/strong&gt; already in the XAP, it needs an additional async operation to download the image specified by &lt;strong&gt;BackImage&lt;/strong&gt; first. The caller of &lt;strong&gt;UpdateTile &lt;/strong&gt;doesn't need to worry about the extra async calls though because the &lt;strong&gt;AsyncWorkHelper &lt;/strong&gt;is waiting for it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Must run on the dispatcher thread (due to use of BitmapImage)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.BeginInvoke(&lt;span style="color: blue;"&gt;delegate&lt;/span&gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt; image = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt;();&lt;br /&gt;&amp;nbsp; image.CreateOptions = &lt;span style="color: #2b91af;"&gt;BitmapCreateOptions&lt;/span&gt;.None;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Handle both success and failure cases with a completion delegate&lt;/span&gt;&lt;br /&gt;&amp;nbsp; image.ImageFailed += (o, e) =&amp;gt; CompleteGetBackBackgroundImage(tileData, &lt;span style="color: blue;"&gt;null&lt;/span&gt;, token);&lt;br /&gt;&amp;nbsp; image.ImageOpened += (o, e) =&amp;gt; CompleteGetBackBackgroundImage(tileData, o &lt;span style="color: blue;"&gt;as&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt;, token);&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Set the source to the remote URI, which will trigger the download&lt;/span&gt;&lt;br /&gt;&amp;nbsp; image.UriSource = tileData.BackImage;&lt;br /&gt;});&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here &lt;strong&gt;CompleteGetBackBackgroundImage &lt;/strong&gt;basically just calls &lt;strong&gt;ComposeTileAndWriteToDisk &lt;/strong&gt;and then calls &lt;strong&gt;NotifySuccess&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Beware of the '@' sign&lt;/h2&gt;
&lt;p&gt;One final tip for those of you writing out tile content - especially it if comes from Twitter, which makes heavy use of the '@' symbol: If your tile's &lt;strong&gt;BackContent&lt;/strong&gt; property is set to a string that begins with an @ sign, the system will treat it as a resource lookup ID (and fail), resulting in your tile displaying something like &lt;strong&gt;"@\Application\Install\{GUID}"&lt;/strong&gt; instead of your intended string.&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/6283.image_5F00_15EBB6B1.png" width="144" height="146" /&gt;&lt;/p&gt;
&lt;p&gt;To combat this, you can use some code like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Set the back of the tile info&lt;/span&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;// Be careful to escape leading '@' signs so they are not confused for resource strings&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt; backText = tileData.BackText;&lt;br /&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (backText.StartsWith(&lt;span style="color: #a31515;"&gt;"@"&lt;/span&gt;))&lt;br /&gt;&amp;nbsp; backText = ZWSP + backText;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;where ZWSP is the Unicode &lt;a href="http://en.wikipedia.org/wiki/Zero-width_space" target="_blank"&gt;zero-width space character&lt;/a&gt;, defined like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Zero-Width-Space; used to escape '@' sign in content&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;char&lt;/span&gt; ZWSP = (&lt;span style="color: blue;"&gt;char&lt;/span&gt;)8203;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This will ensure that the first character is not an @ sign, but it also isn't visible so won't affect your output.&lt;/p&gt;
&lt;p&gt;That just about wraps it up! Remember, you can find the code in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;Part 1&lt;/a&gt; or you can read about the &lt;strong&gt;AsyncWorkHelper &lt;/strong&gt;in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;Part 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10185874" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Mix/">Mix</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Background Agents - Part 2 of 3</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx</link><pubDate>Wed, 13 Jul 2011 03:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10185870</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10185870</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10185870</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;Part 1&lt;/a&gt; we looked at a simple Windows Phone application that used a background agent to periodically show a toast and / or update a tile when a new tweet was found for a particular search term. The code we are discussing in this post can be found at the end of &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;that post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Part of the contract of a background agent is that you must call &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.backgroundagent.notifycomplete(VS.92).aspx" target="_blank"&gt;NotifyComplete&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.backgroundagent.abort(VS.92).aspx" target="_blank"&gt;Abort&lt;/a&gt; exactly once when your agent has completed processing. This is pretty easy if you have a sequential set of synchronous steps to complete, like reading and writing from IsoStore, but it is harder when you have one or more asynchronous operations or when you need to throw work over to the Dispatcher thread, since you can't rely on things like &lt;strong&gt;try-catch &lt;/strong&gt;blocks to handle errors.&lt;/p&gt;
&lt;p&gt;It's possible (but not desirable) to try and serialize the asynchronous operations with simple &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.waithandle(VS.95).aspx" target="_blank"&gt;WaitHandle&lt;/a&gt; operations, but doing that might mean you run out of your agent runtime before all the operations complete. Better to do them in parallel, and then have a simple way of waiting until they have all completed (successfully or otherwise) and then calling &lt;strong&gt;NotifyComplete&lt;/strong&gt; / &lt;strong&gt;Abort&lt;/strong&gt; as necessary.&lt;/p&gt;
&lt;p&gt;Such was the case with the Twitter background agent. It performs network downloads to get tweets from &lt;a href="http://twitter.com/" target="_blank"&gt;twitter.com&lt;/a&gt;, and it also needs to dispatch to the UI thread to compose the background tile image. Initially I used a &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent(VS.95).aspx" target="_blank"&gt;ManualResetEvent&lt;/a&gt; and did something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: #2b91af;"&gt;ManualResetEvent&lt;/span&gt; evt;&lt;br /&gt; &lt;br /&gt;&lt;span style="color: green;"&gt;// Main agent code&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; AgentCode()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; evt = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt;&amp;nbsp; DoAsyncWork();&lt;br /&gt;&amp;nbsp; evt.WaitOne();&lt;br /&gt; &lt;br /&gt;&amp;nbsp; evt.Reset();&lt;br /&gt;&amp;nbsp; DoMoreAsyncWork();&lt;br /&gt;&amp;nbsp; evt.WaitOne();&lt;br /&gt; &lt;br /&gt;&amp;nbsp; NotifyComplete();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; DoAsyncWork()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Lots of work on another thread...&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; evt.Set();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; DoMoreAsyncWork()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Lots of work on another thread...&lt;/span&gt;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; evt.Set();&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;It works, but it's not terribly efficient. We could be doing the second bit of async work at the same time as the first one, especially if they both involve something like network access that spends most of its time waiting for bits anyway. What we need is a helper library to let us queue up a bunch of async work, set it all free, and then wait for them all to report done-ness. Now, you could consider using the &lt;a href="http://msdn.microsoft.com/en-us/vstudio/gg316360.aspx" target="_blank"&gt;Async CTP&lt;/a&gt;, but it's still a "technology preview" (ie, not a shipping product) and it has issues with background agents right now because the helper library references XNA (which is &lt;a href="http://msdn.microsoft.com/en-us/library/hh202962(VS.92).aspx" target="_blank"&gt;a no-no for agents&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Enter the &lt;strong&gt;AsyncWorkloadHelper&lt;/strong&gt; library!&lt;/p&gt;
&lt;h1&gt;The AsyncWorkloadHelper library&lt;/h1&gt;
&lt;p&gt;The background agent project contains a library named &lt;strong&gt;AsyncWorkloadHelper&lt;/strong&gt;. It is pretty simple; the public API looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/6560.image_5F00_51E6EDA0.png" width="579" height="293" /&gt;&lt;/p&gt;
&lt;p&gt;Both classes are generic and require two types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TParam&lt;/strong&gt;, the type of the parameter that you will pass to your async methods. Use &lt;strong&gt;object &lt;/strong&gt;if you have varying parameter types&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TResult&lt;/strong&gt;, the type of the return value of the async methods. Again, use &lt;strong&gt;object &lt;/strong&gt;if you have varying return types&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using the library is very simple; here's some code from the twitter agent itself that generates live tile background images:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Asynchronously generate the bitmap images (front and back)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; workManager = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;AsyncWorkManager&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ExtendedTileData&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; backgroundImageWorker = workManager.AddWorkItem(GetBackgroundImage, tileData);&lt;br /&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; backBackgroundImageWorker = workManager.AddWorkItem(GetBackBackgroundImage, tileData);&lt;br /&gt; &lt;br /&gt;&lt;span style="color: green;"&gt;// Wait for the async operations to complete&lt;/span&gt;&lt;br /&gt;workManager.WaitAll();&lt;br /&gt; &lt;br /&gt;&lt;span style="color: green;"&gt;// Set the front of the tile&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (backgroundImageWorker.Error == &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;br /&gt;&amp;nbsp; data.BackgroundImage = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Uri&lt;/span&gt;(ISOSTORE_SCHEME + backgroundImageWorker.Result);&lt;br /&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;br /&gt;&amp;nbsp; data.BackgroundImage = EMPTY_URI;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;It's pretty self-explanatory:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create an instance of the &lt;strong&gt;AsyncWorkManager&lt;/strong&gt; with the appropriate types parameters&lt;/li&gt;
&lt;li&gt;Call &lt;strong&gt;AddWorkItem&lt;/strong&gt; for each work item you intend to execute&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;The first parameter is the delegate that will do the work&lt;/li&gt;
&lt;li&gt;The second parameter is the parameter to pass to the method&lt;/li&gt;
&lt;li&gt;The return value is a &lt;strong&gt;WorkloadInfo&lt;/strong&gt; object you will use later&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Call &lt;strong&gt;WaitAll&lt;/strong&gt; to wait for them all to complete (there's also a version with a timeout if you don't want to wait indefinitely)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;You could also listen for the &lt;strong&gt;WorkComplete &lt;/strong&gt;event if you like&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Once work is done, check the &lt;strong&gt;Error&lt;/strong&gt; property of the &lt;strong&gt;WorkloadInfo&lt;/strong&gt;&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;If it is &lt;strong&gt;null&lt;/strong&gt;, the result is valid and you can get it via the &lt;strong&gt;Result&lt;/strong&gt; property&lt;/li&gt;
&lt;li&gt;Otherwise, you can do something with the &lt;strong&gt;Error&lt;/strong&gt; itself&lt;/li&gt;
&lt;/ul&gt;
&lt;/ol&gt;
&lt;p&gt;That's it! The methods that are called by the worker - in this case, &lt;strong&gt;GetBackgroundImage &lt;/strong&gt;and &lt;strong&gt;GetBackBackgroundImage &lt;/strong&gt;- only have one responsibility: to call &lt;strong&gt;NotifySuccess &lt;/strong&gt;or &lt;strong&gt;NotifyFailure &lt;/strong&gt;when they are done. For example, here's the complete listing for &lt;strong&gt;GetBackgroundImage&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Asynchronously gets the background image for a specific tweet&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"tileData"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The tile data to add to the image for&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"token"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The completion token&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; GetBackgroundImage(&lt;span style="color: #2b91af;"&gt;ExtendedTileData&lt;/span&gt; tileData, &lt;span style="color: #2b91af;"&gt;WorkloadInfo&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ExtendedTileData&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;&amp;gt; token)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Must run on the dispatcher thread (due to use of BitmapImage)&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Deployment&lt;/span&gt;.Current.Dispatcher.BeginInvoke(&lt;span style="color: blue;"&gt;delegate&lt;/span&gt;&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt; bi = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;BitmapImage&lt;/span&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bi.CreateOptions = &lt;span style="color: #2b91af;"&gt;BitmapCreateOptions&lt;/span&gt;.None;&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Pull the standard background image out of our app package&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bi.SetSource(&lt;span style="color: #2b91af;"&gt;Application&lt;/span&gt;.GetResourceStream(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"background.png"&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;UriKind&lt;/span&gt;.Relative)).Stream);&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Compose the image and write to disk&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;string&lt;/span&gt; fileName = ComposeTileAndWriteToDisk(bi, FRONT_IMAGE_OPACITY, tileData.FrontText, &lt;span style="color: #a31515;"&gt;"frontimage"&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Complete the async operation&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token.NotifySuccess(fileName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;catch&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;Exception&lt;/span&gt; ex)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; token.NotifyFailure(ex);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; });&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is pretty simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The signature for the method is: &lt;strong&gt;TResult&lt;/strong&gt; &lt;em&gt;MethodName&lt;/em&gt;(&lt;strong&gt;TParam &lt;/strong&gt;&lt;em&gt;param&lt;/em&gt;, &lt;strong&gt;WorkloadInfo&amp;lt;TParam, TResult&amp;gt;&lt;/strong&gt; &lt;em&gt;token&lt;/em&gt;), where the the type params are dictated by the &lt;strong&gt;AsyncWorkManager &lt;/strong&gt;that is being used&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;In this case, &lt;strong&gt;TParam &lt;/strong&gt;is &lt;strong&gt;ExtendedTileData &lt;/strong&gt;and &lt;strong&gt;TResult &lt;/strong&gt;is &lt;strong&gt;string&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;In this case, the code has to be dispatched to the UI thread since we'll be composing some bitmap images&lt;/li&gt;
&lt;li&gt;The async code is wrapped in a &lt;strong&gt;try-catch&lt;/strong&gt;; if it fails we will call &lt;strong&gt;NotifyFailure &lt;/strong&gt;with the error (which will propagate back to &lt;strong&gt;WorkloadInfo.Error&lt;/strong&gt;)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;If the synchronous code fails, the error is automatically caught by the library&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Assuming nothing goes wrong, we call &lt;strong&gt;NotifySuccess&lt;/strong&gt;, passing in the result of the function&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course the "interesting" bit is tied up in that &lt;strong&gt;ComposeTileAndWriteToDisk&lt;/strong&gt; method, but it is a synchronous method that, well, composes some content into a tile image and writes it to IsoStore, returning the full filename.&lt;/p&gt;
&lt;h1&gt;How it works&lt;/h1&gt;
&lt;p&gt;The implementation of the &lt;strong&gt;AsyncWorkManager &lt;/strong&gt;is pretty basic. Of course you can check out the code for yourself, but in a nut-shell it works like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is a counter, &lt;strong&gt;outstandingItems&lt;/strong&gt;, that counts how many remaining items there are to complete. This starts at zero.&lt;/li&gt;
&lt;li&gt;There is an event, &lt;strong&gt;startEvent&lt;/strong&gt;, that is used to "hold back" all the work until the client is ready for them to start. This starts non-set.&lt;/li&gt;
&lt;li&gt;There is another event, &lt;strong&gt;completionEvent&lt;/strong&gt;, that is used to wait until all work is complete. This starts non-set.&lt;/li&gt;
&lt;li&gt;Calling &lt;strong&gt;AddWorkItem &lt;/strong&gt;increments &lt;strong&gt;outstandingItems &lt;/strong&gt;and kicks off a &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool(VS.95).aspx" target="_blank"&gt;ThreadPool&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;thread that first waits for &lt;strong&gt;startEvent&lt;/strong&gt; to be set, then calls the associated method&lt;/li&gt;
&lt;li&gt;Calling &lt;strong&gt;WaitOne &lt;/strong&gt;implicitly calls &lt;strong&gt;Start&lt;/strong&gt;, then waits for the &lt;strong&gt;completionEvent&lt;/strong&gt; to become set.&lt;/li&gt;
&lt;li&gt;Start sets &lt;strong&gt;startEvent&lt;/strong&gt;, releasing all the threads&lt;/li&gt;
&lt;li&gt;As each work item completes, it calls &lt;strong&gt;NotifySuccess &lt;/strong&gt;or &lt;strong&gt;NotifyFailure&lt;/strong&gt;. These stash the appropriate values into the &lt;strong&gt;WorkloadInfo &lt;/strong&gt;class and then call the internal &lt;strong&gt;CompleteWorkItem &lt;/strong&gt;method&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CompleteWorkItem &lt;/strong&gt;decrements &lt;strong&gt;outstandingItems&lt;/strong&gt;, and if the value is zero then it sets the &lt;strong&gt;completionEvent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;completionEvent &lt;/strong&gt;releases the &lt;strong&gt;WaitOne &lt;/strong&gt;call and also raises the &lt;strong&gt;WorkComplete &lt;/strong&gt;event&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So no rocket science, just a small set of framework code to make things easy for you.&lt;/p&gt;
&lt;p&gt;That said, this code isn't particularly well tested, nor have I really used it outside of this project. For example, I don't really know if making the API generic has value (it did for me, since the methods I wanted to call had the same signature) but maybe that's too messy and &lt;strong&gt;object &lt;/strong&gt;would just work better in general. I also don't know how it really performs in error conditions or with large numbers of work items (more than fit into the thread pool, for example)... use at your own risk!&lt;/p&gt;
&lt;p&gt;As a reminder, you can get the project at &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx" target="_blank"&gt;Part 1&lt;/a&gt;. Next up, &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-3-of-3.aspx" target="_blank"&gt;Part 3&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10185870" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Mix/">Mix</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Background Agents - Part 1 of 3</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx</link><pubDate>Mon, 11 Jul 2011 07:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10185105</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10185105</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10185105</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/07/11/background-agents-part-1-of-3.aspx#comments</comments><description>&lt;p&gt;This post has (errr, "These posts have") been a long time coming. They are based off the &lt;a href="http://channel9.msdn.com/Events/MIX/MIX11?sort=sequential&amp;amp;direction=desc&amp;amp;term=&amp;amp;t=windows%2Bphone&amp;amp;s=peter%2Btorr" target="_blank"&gt;Mix 11&lt;/a&gt; and &lt;a href="http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011?sort=sequential&amp;amp;direction=desc&amp;amp;term=&amp;amp;s=peter%2Btorr" target="_blank"&gt;TechEd 2011&lt;/a&gt; sessions I gave a loooooong time ago, but despite my best efforts I've not been able to post anything to my blog for some time. Partly it was due to a family vacation in &lt;a href="http://www.nps.gov/yell/index.htm" target="_blank"&gt;Yellowstone National Park&lt;/a&gt; (go there! it's incredible!) and partly it's due to being rather busy getting the finishing touches on Mango and preparing for what's next. But mostly it's due to the fact that every time I sit down to blog about it, I add some new feature to the code or make it more extensible... this is almost (&lt;em&gt;almost!&lt;/em&gt;) a complete app at this stage, but it's not quite good enough to put in the marketplace.&lt;/p&gt;
&lt;p&gt;This series of three posts will demonstrate the basics of &lt;a href="http://msdn.microsoft.com/en-us/library/hh202942(VS.92).aspx" target="_blank"&gt;background agents&lt;/a&gt; in Mango, and will throw in a couple of helper libraries as well (that is what &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;parts 2&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-3-of-3.aspx" target="_blank"&gt;3&lt;/a&gt; are about). The sample app, as seen in the aforementioned Mix / TechEd demos, is a simple Twitter viewer that uses a background agent to periodically &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltoast(VS.92).aspx" target="_blank"&gt;show a toast&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/hh202979(VS.92).aspx" target="_blank"&gt;update the application's tile&lt;/a&gt; if there are new tweets since the last tame the app or the agent ran.&lt;/p&gt;
&lt;h1&gt;&lt;/h1&gt;
&lt;h1&gt;The foreground app&lt;/h1&gt;
&lt;p&gt;The foreground app for this particular demo isn't very interesting. It shows a list of recent tweets for a given search term (the hard-coded default is, of course, &lt;strong&gt;wp7dev&lt;/strong&gt;) and if you tap on any of the items it shows the tweet in full, complete with the user's background image and the ability to follow any links in the tweet. It's not smart enough to link-ify #hashtags or @usernames, etc. so it doesn't suffice as a real twitter client; it's just enough for someone to casually keep up with a search term.&lt;/p&gt;
&lt;p&gt;The app looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/2235.image_5F00_20B6F2C2.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/1738.image_5F00_thumb_5F00_1F7259E3.png" width="130" height="240" /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp; &lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/4061.image_5F00_7118D435.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/2620.image_5F00_thumb_5F00_2F9E21DC.png" width="130" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nothing too special. The only interesting bit on the app is the "enable agent" check box at the bottom-left of the screen, which is where the magic happens, as they say.&lt;/p&gt;
&lt;p&gt;When you click the "enable agent" button, it runs this code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Starts the search agent and runs it for 1 day&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; StartSearchAgent()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;PeriodicTask&lt;/span&gt; task = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;PeriodicTask&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"twitter"&lt;/span&gt;);&lt;br /&gt;&amp;nbsp; task.Description = &lt;span style="color: #a31515;"&gt;"Periodically checks for new tweets and updates the tile on the start screen."&lt;/span&gt; +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #a31515;"&gt;" Will also show a toast during normal 'waking' hours (won't wake you up at night!)"&lt;/span&gt;;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; task.ExpirationTime = &lt;span style="color: #2b91af;"&gt;DateTime&lt;/span&gt;.Now.AddDays(1);&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;ScheduledActionService&lt;/span&gt;.Add(task);&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;catch&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;InvalidOperationException&lt;/span&gt;)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color: #a31515;"&gt;"Can't schedule agent; either there are too many other agents scheduled or you have disabled this agent in Settings."&lt;/span&gt;);&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The code is pretty straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.periodictask(VS.92).aspx" target="_blank"&gt;PeriodicTask&lt;/a&gt;, which is the main class you use to describe the behaviour of the background agent. A periodic task runs every 30 minutes for about 25 seconds, give or take.
&lt;ul&gt;
&lt;li&gt;If you'd prefer to run for much longer - but only when the phone is plugged in and on WiFi - you can create a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.resourceintensivetask(VS.92).aspx" target="_blank"&gt;ResourceIntensiveTask&lt;/a&gt; instead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Give the task a &lt;strong&gt;Description&lt;/strong&gt;, which will show up in the system UI under &lt;strong&gt;settings &lt;/strong&gt;-&amp;gt; &lt;strong&gt;applications&lt;/strong&gt; -&amp;gt; &lt;strong&gt;background tasks&lt;/strong&gt;. This text will explain to the user what your agent is doing and will help them determine whether or not to disable the agent at some future point in time.&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;ExpirationTime &lt;/strong&gt;for 1 day from now. You can specify an expiration date up to 14 days in the future, but in order to be kind to the batter this app defaults to 1 day.&lt;/li&gt;
&lt;li&gt;Try to add the task to the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledactionservice(VS.92).aspx" target="_blank"&gt;ScheduledActionService&lt;/a&gt;. This might fail if the user has disabled the agent in settings or if there are already too many other agents running on the phone.
&lt;ul&gt;
&lt;li&gt;There's not really a good way to tell which it is, but the good new is that the remedy is always to tell the user to go to the settings page and enable your agent (and / or disable some other agents).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And that's all there is to it! Now the system will happily run your agent every ~30 minutes and let it do its thing. Hooray!&lt;/p&gt;
&lt;h1&gt;The background agent&lt;/h1&gt;
&lt;p&gt;The agent is also pretty simple. As you can read about &lt;a href="http://msdn.microsoft.com/en-us/library/hh202941(VS.92).aspx" target="_blank"&gt;in the docs&lt;/a&gt;, you basically add a background agent project to your solution and then implement the work you want to do in the &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledtaskagent.oninvoke(VS.92).aspx" target="_blank"&gt;OnInvoke&lt;/a&gt; method of your class. A few notes about agents up-front:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your agent &lt;strong&gt;must &lt;/strong&gt;derive from &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledtaskagent(VS.92).aspx" target="_blank"&gt;ScheduledTaskAgent&lt;/a&gt; and you must override &lt;strong&gt;OnInvoke&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Your agent &lt;strong&gt;must &lt;/strong&gt;be correctly registered in WMAppManifest.xml of the foreground project
&lt;ul&gt;
&lt;li&gt;Visual Studio does this for you automatically, but if you change the name of the class or of the project you will need to update the XML file&lt;/li&gt;
&lt;li&gt;Cheat sheet: &lt;strong&gt;Specifier &lt;/strong&gt;= &lt;strong&gt;ScheduledTaskAgent&lt;/strong&gt;, &lt;strong&gt;Source &lt;/strong&gt;= &lt;em&gt;[assembly name]&lt;/em&gt;, &lt;strong&gt;Type &lt;/strong&gt;= &lt;em&gt;[fully qualified type name]&lt;/em&gt;, &lt;strong&gt;Name &lt;/strong&gt;= &lt;em&gt;[whatever you want]&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Your agent project (and any projects it references) &lt;strong&gt;must &lt;/strong&gt;be referenced by the foreground project, even if you never use it (this is so that it is correctly added to the XAP)&lt;/li&gt;
&lt;li&gt;Your foreground app &lt;strong&gt;never &lt;/strong&gt;explicitly calls into the agent (they are separate processes) but if you want you can instantiate an instance of the agent class inside your foreground app in order to share code (using a shared library might be a better approach, though)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just in case you missed it (and for search-engine-friendliness):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you change your agent's project name, namespace, or class name, you &lt;strong&gt;must &lt;/strong&gt;update WMAppManifest.xml for the new metadata&lt;/li&gt;
&lt;li&gt;If you reference another assembly from the agent, you &lt;strong&gt;must &lt;/strong&gt;also reference it from the foreground app to ensure it makes it into the XAP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you fail to do this, your agent will not load at all. If you run it under the debugger with the break on all exceptions turned on, you will get a &lt;strong&gt;FileNotFoundException &lt;/strong&gt;stating that it can't find your assembly or one of the assemblies it relies on.&lt;/p&gt;
&lt;p&gt;Anyway, back to our story. The agent's work looks like this (we'll get into the guts of it later):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Called by the system when there is work to be done&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;param name=&lt;/span&gt;&lt;span style="color: gray;"&gt;"Task"&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: green;"&gt;The task representing the work to be done&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; OnInvoke(&lt;span style="color: #2b91af;"&gt;ScheduledTask&lt;/span&gt; Task)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Read the search term from IsoStore settings; in a more complex scenario you might&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// have multiple tiles and read each tile's term from a different setting&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IsolatedStorageSettings&lt;/span&gt; settings = &lt;span style="color: #2b91af;"&gt;IsolatedStorageSettings&lt;/span&gt;.ApplicationSettings;&lt;br /&gt;&amp;nbsp; TweetSearchTerm = settings[&lt;span style="color: #a31515;"&gt;"searchTerm"&lt;/span&gt;].ToString();&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Get the tweets from the library&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;TwitterHelper&lt;/span&gt;.GetFirstTweet(TweetSearchTerm, tweet =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Don't do any work if this is invalid or the same as the most recently-seen tweet&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (tweet.Id != &lt;span style="color: #2b91af;"&gt;Tweet&lt;/span&gt;.InvalidId &amp;amp;&amp;amp; tweet.Id != settings[&lt;span style="color: #a31515;"&gt;"lastTweetId"&lt;/span&gt;].ToString())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; settings[&lt;span style="color: #a31515;"&gt;"lastTweetId"&lt;/span&gt;] = tweet.Id;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; settings.Save();&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Show the toast&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;ToastHelper&lt;/span&gt;.ShowToast(tweet.AuthorAlias, tweet.TweetText, &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"/DetailsPage.xaml?id="&lt;/span&gt; + tweet.Id, &lt;span style="color: #2b91af;"&gt;UriKind&lt;/span&gt;.Relative));&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Update the tile&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;TileHelper&lt;/span&gt;.UpdateTile(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;ExtendedTileData&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FrontText = &lt;span style="color: #a31515;"&gt;"latest tweet"&lt;/span&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FrontTitle = TweetSearchTerm,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackText = tweet.TweetText,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackTitle = tweet.AuthorAlias,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BackImage = tweet.AvatarUri,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Done!&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NotifyComplete();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;What's going on here?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First we get the search term from the &lt;strong&gt;ApplicationSettings &lt;/strong&gt;(this is set in the foreground app)&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;As noted above, this is currently set to &lt;strong&gt;wp7dev&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Then we call a handy-dandy method &lt;strong&gt;GetFirstTweet &lt;/strong&gt;to retrieve the first tweet that matches our search term
&lt;ul&gt;
&lt;li&gt;This is an asynchronous call, of course, since it goes out to the web&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When the call returns, we check if the tweet is valid and whether it is different from the last tweet we saw (which is also retrieved from &lt;strong&gt;ApplicationSettings&lt;/strong&gt;)
&lt;ul&gt;
&lt;li&gt;If the tweet is invalid or not new, we skip to the end&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The current tweet is saved as the last-seen tweet, so we don't show it again next time&lt;/li&gt;
&lt;li&gt;We use a helper method to show a toast to the user with the tweet's author and text. We also use a deep link into the application so that tapping on the toast will launch directly into the details page for that toast
&lt;ul&gt;
&lt;li&gt;The same technique as used in the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx" target="_blank"&gt;alarms and reminders example&lt;/a&gt; is used to show a "home" button in the UI in this case&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;We use another helper method to update the primary tile with the tweet information, including the author's avatar (this will appear on the back of the tile)&lt;/li&gt;
&lt;li&gt;Finally, we call the all-important &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.backgroundagent.notifycomplete(VS.92).aspx" target="_blank"&gt;NotifyComplete&lt;/a&gt;method to let the system know we completed successfully.
&lt;ul&gt;
&lt;li&gt;If we had hit an unrecoverable error, we could call &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.backgroundagent.abort(VS.92).aspx" target="_blank"&gt;Abort&lt;/a&gt; instead&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;The importance of calling NotifyComplete at the right time cannot be overstated!&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;Failure to call &lt;strong&gt;NotifyComplete &lt;/strong&gt;at all will cause the system to think you timed-out, and then in the foreground if you query &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledtask.lastexitreason(VS.92).aspx" target="_blank"&gt;LastExitReason&lt;/a&gt; you will get a failure code &lt;strong&gt;ExecutionTimeExceeded&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Calling &lt;strong&gt;NotifyComplete &lt;/strong&gt;too early will immediately terminate your process, leaving any remaining work on background threads incomplete (although the system will happily report that you &lt;strong&gt;Completed &lt;/strong&gt;successfully!)&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;Luckily there is a simple way to deal with this, as we shall see in Part 2 of the post.&lt;/p&gt;
&lt;h1&gt;A handy tip for agent debugging&lt;/h1&gt;
&lt;p&gt;One of the problems with debugging agents is that the very act of using the debugger changes the way your agent executes. In particular, when the debugger is attached &lt;em&gt;both the runtime quota and the memory quota are ignored&lt;/em&gt;, leaving you with infinite time and memory to (ab)use. This is necessary for the debugger to work correctly (imagine trying to complete a debug session in only 25 seconds!) but introduces issues if the thing you're trying to debug is a memory and / or execution time issue.&lt;/p&gt;
&lt;p&gt;Now back in the olden days - when we used to have to walk to school uphill in &lt;strong&gt;both &lt;/strong&gt;directions - we didn't have fancy-schmancy graphical debuggers. We had &lt;a href="http://msdn.microsoft.com/en-us/library/wc7014hz.aspx" target="_blank"&gt;printf&lt;/a&gt;! Now &lt;strong&gt;printf &lt;/strong&gt;(or its modern debugging equivalent, &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.debug.writeline(VS.95).aspx" target="_blank"&gt;Debug.WriteLine&lt;/a&gt;) doesn't really help with an agent if you can't have the debugger attached, so there's not much you can do. Obviously you can write out logs to a log file and then read them off the device with the &lt;a href="http://msdn.microsoft.com/en-us/library/hh286408(VS.92).aspx" target="_blank"&gt;Isolated Storage Explorer tool&lt;/a&gt;, or if you're brave enough you can &lt;a href="http://nicksnettravels.builttoroam.com/post/2011/01/19/Windows-Phone-7-Console-Window-on-64-bit-machine.aspx" target="_blank"&gt;enable console spew from the emulator&lt;/a&gt;, but if you just want to display a tiny bit of text - like, say, the amount of memory you're currently using or the amount of time you've been executing... why not use a &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.shell.shelltoast(VS.92).aspx" target="_blank"&gt;toast&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;The agent includes a method &lt;strong&gt;WriteDebugStats&lt;/strong&gt; that is used to write some memory statistics to a toast (and to a tile for good measure!). Because toasts "stack up" in the shell and are displayed for several seconds before being replaced by the next toast, you can actually queue up several messages inside toasts that can be used to convey debug information while not under the debugger.&lt;/p&gt;
&lt;p&gt;The method looks like this, using the same helper methods as before to show the toast and a tile update (the memory values are all based on calls to &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.devicestatus.applicationpeakmemoryusage(VS.92).aspx" target="_blank"&gt;ApplicationPeakMemoryUsage&lt;/a&gt; API):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt; Writes out debug stats to a toast and a secondary tile (if it exists)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: gray;"&gt;///&lt;/span&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; WriteDebugStats()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;const&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;double&lt;/span&gt; ONE_MEGABYTE = 1024 * 1024;&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;double&lt;/span&gt; initial = (&lt;span style="color: blue;"&gt;double&lt;/span&gt;)initialMemory / ONE_MEGABYTE;&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;double&lt;/span&gt; beforeTile = (&lt;span style="color: blue;"&gt;double&lt;/span&gt;)beforeTileMemory / ONE_MEGABYTE;&lt;br /&gt;&amp;nbsp; &lt;span style="color: blue;"&gt;double&lt;/span&gt; final = (&lt;span style="color: blue;"&gt;double&lt;/span&gt;)finalMemory / ONE_MEGABYTE;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt; duration = &lt;span style="color: #2b91af;"&gt;DateTime&lt;/span&gt;.Now - startTime;&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Show a toast&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;ToastHelper&lt;/span&gt;.ShowToast(&lt;span style="color: #a31515;"&gt;"Mem / time"&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #a31515;"&gt;"{0:#.#}-{1:#.#}-{2:#.#}MB / {3:#.#}s"&lt;/span&gt;, initial, beforeTile, final, duration.TotalSeconds), &lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;br /&gt; &lt;br /&gt;&amp;nbsp; &lt;span style="color: green;"&gt;// Update the debug tile (if it is pinned)&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;TileHelper&lt;/span&gt;.UpdateTile(&lt;span style="color: #a31515;"&gt;"DEBUG_TILE"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"debug info"&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"debug info"&lt;/span&gt;, &lt;span style="color: blue;"&gt;string&lt;/span&gt;.Format(TweetSearchTerm + &lt;span style="color: #a31515;"&gt;": {0:#.#}MB, {1:#.#}s"&lt;/span&gt;, final, duration.TotalSeconds));&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the app is running in debug mode, it will display a "debug" button on the main page that will pin a secondary tile to start that is used to display the debug info.&lt;/p&gt;
&lt;p&gt;Another handy hint - use the new &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledactionservice.launchfortest(VS.92).aspx" target="_blank"&gt;LaunchForTest&lt;/a&gt; API to launch your agent whenever you want - this replaces the old (Beta 1) behaviour of launching the agent whenever &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledactionservice.add(VS.92).aspx" target="_blank"&gt;Add&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.scheduler.scheduledactionservice.find(VS.92).aspx" target="_blank"&gt;Find&lt;/a&gt; was called and the debugger was attached (it was a rather annoying "feature"). You can even call &lt;strong&gt;LaunchForTest &lt;/strong&gt;from the background agent itself, letting it run in perpetuity (but, of course, only on side-loaded dev projects; a shipping marketplace app can't call this method). If you run the project in "Debug" mode you will see button that lets you run the agent immediately (there are is a short delay giving you enough time to exit the app so that the toast will appear).&lt;/p&gt;
&lt;p&gt;That's it for Part 1 - the project is zipped up below, and we'll discuss more of the project in &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-2-of-3.aspx" target="_blank"&gt;parts 2&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/07/12/background-agents-part-3-of-3.aspx" target="_blank"&gt;3&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10185105" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-18-51-05/BackgroundAgentDemo.zip" length="115903" type="application/zip" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Mix/">Mix</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Alarms and Notifications in Mango</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx</link><pubDate>Sat, 28 May 2011 23:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10169349</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10169349</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10169349</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx#comments</comments><description>&lt;p&gt;Here's the first of several posts about the new multitasking features in Windows Phone Mango. Alarms and Notifications is a good place to start because it is the simplest of the new multitasking features (outside of Fast App Switching, but that's not really an API) and it doesn't require running code in the background; it just leverages a system service to notify the user when a specific time is met. &lt;/p&gt;
&lt;p&gt;If you haven't seen it yet, you can watch my &lt;a target="_blank" href="http://channel9.msdn.com/Events/MIX/MIX11/DVC11"&gt;Mix 11 video&lt;/a&gt; (or the &lt;a target="_blank" href="http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WPH308"&gt;Tech Ed version&lt;/a&gt;, which includes more conceptual stuff and less code).&lt;/p&gt;
&lt;p&gt;The sample application is a very basic "todo" application that is impossible to build on Windows Phone 7 due to the need to display a reminder at a future point in time (at Mix the example was a cake-baking app :-) ). It isn't very functional and it isn't very pretty, but it illustrates the core concepts needed to use the Alarms and Reminders service. &lt;/p&gt;
&lt;h2&gt;Here are a couple of screenshots&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/4503.reminder_5F00_screen_5F00_shot_5F00_04703ABC.jpg"&gt;&lt;img height="244" width="148" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/8206.reminder_5F00_screen_5F00_shot_5F00_thumb_5F00_3118F495.jpg" alt="reminder_screen_shot" border="0" title="reminder_screen_shot" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" /&gt;&lt;/a&gt;&amp;nbsp; &lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/3414.reminder_5F00_details_5F00_screen_5F00_37CBFE18.jpg"&gt;&lt;img height="244" width="148" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/1832.reminder_5F00_details_5F00_screen_5F00_thumb_5F00_3E7F079B.jpg" alt="reminder_details_screen" border="0" title="reminder_details_screen" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The code is provided below in a ZIP, but let's look at the salient bits of code.&lt;/p&gt;
&lt;h2&gt;Setting up the reminder&lt;/h2&gt;
&lt;p&gt;When you click the "remind me!" button in the item detail screen, the following piece of code runs (where &lt;strong&gt;item &lt;/strong&gt;represents the ViewModel item that is bound to the page instance):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Setup the reminder&lt;/span&gt;
&lt;span style="color: #2b91af;"&gt;Reminder&lt;/span&gt; r = &lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Reminder&lt;/span&gt;(item.Title);
r.Title = item.Title;
r.Content = item.Description;
r.BeginTime = &lt;span style="color: #2b91af;"&gt;DateTime&lt;/span&gt;.Now.AddSeconds(15); &lt;span style="color: green;"&gt;// item.DueDate;&lt;/span&gt;
r.ExpirationTime = r.BeginTime;
r.NavigationUri = NavigationService.CurrentSource;
 
&lt;span style="color: green;"&gt;// Add it to the service&lt;/span&gt;
&lt;span style="color: #2b91af;"&gt;ScheduledActionService&lt;/span&gt;.Add(r);&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reminder &lt;/strong&gt;is a new type in Mango that represents a possibly-recurring reminder that behaves just like the calendar reminders built-in to the phone (you can also use an &lt;strong&gt;Alarm&lt;/strong&gt;, which is similar to a reminder but has slightly different behaviour - you should experiment with it and explore via IntelliSense). &lt;/p&gt;
&lt;p&gt;The constructor takes a string which is used as the &lt;strong&gt;Name &lt;/strong&gt;for the reminder. This lets you locate the reminder later on to check if it has expired or not, to remove it if it's no longer necessary, and so on. Note that you can create many reminders - in this example, one for each ToDo item.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Title &lt;/strong&gt;and &lt;strong&gt;Content&lt;/strong&gt; properties are used to populate the text in the reminder when it pops up on-screen, like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/4186.reminder_5F00_popup_5F00_69576BAD.jpg"&gt;&lt;img height="244" width="148" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-30-21-metablogapi/3513.reminder_5F00_popup_5F00_thumb_5F00_421D2278.jpg" alt="reminder_popup" border="0" title="reminder_popup" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that you do not have control over the Snooze options, nor whether or not the "snooze" and "dismiss" buttons appear - they are all controlled by the system.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;BeginTime &lt;/strong&gt;is the time that the reminder first goes off (in this case, we set it to 15 seconds from now so that it is easy to demo), and if you set the &lt;strong&gt;RecurrenceType &lt;/strong&gt;of the reminder (not used in this sample) it also determines the beginning of the reminder pattern (daily, weekly, etc,)&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;ExpirationTime &lt;/strong&gt;is the time that the reminder should stop being scheduled. In this example it doesn't affect the UI (since we are not creating a recurring reminder) but it will be used later on in the code to determine whether we should clean-up old reminders or not. In general you should set this for all reminders since it will make your code easier.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;NavigationUri &lt;/strong&gt;specifies the page to launch if the user taps on the reminder title / content when the reminder fires (little-known fact about WP7 is that this works even for the built-in calendar app, but only if the phone isn't currently locked). If you don't specify a URI, your app will just launch normally. Note that if your app is currently in the foreground when the reminder is fired, tapping on the title / content will dismiss the reminder but will not cause a navigation (since your app is already running).&lt;/p&gt;
&lt;p&gt;Finally we add it to the &lt;strong&gt;ScheduledActionService&lt;/strong&gt;, which will do the job of firing the reminder when the &lt;strong&gt;BeginTime&lt;/strong&gt; is reached (note that the reminders are only accurate to the nearest minute, and in the beta the emulator gets less accurate over time... just close and re-open it if you find reminders are not firing at all).&lt;/p&gt;
&lt;h2&gt;Cleaning up the reminder&lt;/h2&gt;
&lt;p&gt;It's just as important to clean things up as it is to create them! The sample uses a simple helper method to do this every time a detail page is navigated to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Removes the reminder if it has expired&lt;/span&gt;
&lt;span style="color: blue;"&gt;void&lt;/span&gt; CleanupOldReminder(&lt;span style="color: #2b91af;"&gt;ToDoItem&lt;/span&gt; item)
{
  &lt;span style="color: blue;"&gt;var&lt;/span&gt; reminder = &lt;span style="color: #2b91af;"&gt;ScheduledActionService&lt;/span&gt;.Find(item.Title);

  &lt;span style="color: green;"&gt;// If found and it has expired, remove it&lt;/span&gt;
  &lt;span style="color: blue;"&gt;if&lt;/span&gt; (reminder != &lt;span style="color: blue;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; reminder.IsScheduled == &lt;span style="color: blue;"&gt;false&lt;/span&gt;)
    &lt;span style="color: #2b91af;"&gt;ScheduledActionService&lt;/span&gt;.Remove(reminder.Name);
}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we see why setting &lt;strong&gt;ExpirationTime &lt;/strong&gt;is important - it let's us check the &lt;strong&gt;IsScheduled &lt;/strong&gt;property to know whether to delete the reminder or not, using the aptly-named &lt;strong&gt;Remove &lt;/strong&gt;method.&lt;/p&gt;
&lt;h2&gt;Dealing with deep links&lt;/h2&gt;
&lt;p&gt;The only other useful thing in this sample is how it deals with the deep links into the application from the reminders. As I've blogged several times before, Windows Phone uses the hardware Back key to navigate to the previous "place", and in the case where the user navigates directly into the details page (as is the case if they tap on the reminder) then the previous place will &lt;em&gt;not &lt;/em&gt;be the main screen of the application, but rather whatever the user was looking at before (another app, the start menu, etc.). To see how this works on the phone, you can create deep links in the built-in apps and note that when you tap on the tile and then hit back, you return to the start menu. Examples of built-in pinnable items are contacts, albums, and playlists. &lt;/p&gt;
&lt;p&gt;Nevertheless, some applications will benefit from enabling the user to navigate from the deep-linked page into the main UI of the application (none of the built-in apps do this, but you can). In this case, after a reminder has fired in the ToDo app, maybe you want to see what other things are left on your list. To do this, we introduce a "home" button on the detail page, but only display it if the Back key won't work:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Only show the GoHome button if there is nothing else on the backstack (ie, this is the first page)&lt;/span&gt;
&lt;span style="color: blue;"&gt;if&lt;/span&gt; (NavigationService.CanGoBack != &lt;span style="color: blue;"&gt;true&lt;/span&gt;)
  goHomeButton.Visibility = &lt;span style="color: #2b91af;"&gt;Visibility&lt;/span&gt;.Visible;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here we check &lt;strong&gt;CanGoBack &lt;/strong&gt;- if it is &lt;strong&gt;true&lt;/strong&gt;, that means the user is navigating the application normally and the Back key will take them home. But if it is &lt;strong&gt;false&lt;/strong&gt;, that means they deep-linked into the page from the reminder and can't use the Back key - instead we'll forward-navigate home. In order to avoid having the detail page on the back stack (which might be confusing), we'll signal to the main page that we want it to clear up the backstack:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: green;"&gt;// Navigate to the home page, and tell it to clear the stack&lt;/span&gt;
&lt;span style="color: blue;"&gt;void&lt;/span&gt; GoHomeClick(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: #2b91af;"&gt;RoutedEventArgs&lt;/span&gt; e)
{
  NavigationService.Navigate(&lt;span style="color: blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color: #a31515;"&gt;"/MainPage.xaml?clear=yes"&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;UriKind&lt;/span&gt;.Relative));
}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then inside the main page, we use a new method &lt;strong&gt;RemoveBackEntry &lt;/strong&gt;to clean up the old entry if it's been requested by the calling application:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre style="font-family: consolas; background: white; color: black; font-size: 13px;"&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color: blue;"&gt;void&lt;/span&gt; OnNavigatedTo(&lt;span style="color: #2b91af;"&gt;NavigationEventArgs&lt;/span&gt; e)
{
  &lt;span style="color: green;"&gt;// If this is a new navigation AND the caller has asked us to remove them from the stack, then do so&lt;/span&gt;
  &lt;span style="color: blue;"&gt;if&lt;/span&gt; (e.NavigationMode == &lt;span style="color: #2b91af;"&gt;NavigationMode&lt;/span&gt;.New &amp;amp;&amp;amp; NavigationContext.QueryString.ContainsKey(&lt;span style="color: #a31515;"&gt;"clear"&lt;/span&gt;))
    NavigationService.RemoveBackEntry();
}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also note that we've added the &lt;strong&gt;NavigationMode &lt;/strong&gt;property on to all the navigation-related &lt;strong&gt;EventArgs&lt;/strong&gt;, making it easier to do things like this (and manage animations, etc.)&lt;/p&gt;
&lt;p&gt;And that's about it!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10169349" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-16-93-49/BackgroundNotificationServiceDemo.zip" length="83429" type="application/zip" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Mix/">Mix</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Mango samples coming soon, no really!</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/05/23/mango-samples-coming-soon.aspx</link><pubDate>Tue, 24 May 2011 01:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10167572</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10167572</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10167572</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/05/23/mango-samples-coming-soon.aspx#comments</comments><description>&lt;p&gt;Now that the consumer features of Mango have &lt;a target="_blank" href="http://www.microsoft.com/presspass/presskits/windowsphone/"&gt;been announced&lt;/a&gt; and the beta developer tools &lt;a href="http://create.msdn.com/en-US/news/WPDT_7.1_Beta"&gt;have been released&lt;/a&gt;, it's time to make good on &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2011/04/21/quot-mango-quot-posts-coming-soon.aspx"&gt;my promise&lt;/a&gt; to make the Mix / TechEd sample code available to all. I'll also try and post the push notifications code from TechEd that I borrowed from Tom Fennel.&lt;/p&gt;
&lt;p&gt;I am in the process of doing this, but it will take a little while; first I need to install the beta software on my home PC to make sure all the demos work just fine (vs from the build I used at TechEd) and then I need to clean things up, add comments, and write a suitably informative post to go with the code.&lt;/p&gt;
&lt;p&gt;In the meantime, you can &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586864-ab15-40e1-bc38-713a95a56a05&amp;amp;displaylang=en"&gt;download the tools&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/ff637516(VS.92).aspx"&gt;crack open the docs&lt;/a&gt;, and start partying on the APIs yourself! If you haven't already watched the talks from Mix or TechEd, you can find them here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a target="_blank" href="http://channel9.msdn.com/Events/MIX/MIX11/DVC11"&gt;Multitasking at Mix&lt;/a&gt; (all code)&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" href="http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WPH308"&gt;Multitasking at TechEd&lt;/a&gt; (half slides, half code); thanks to Darin Miller for the original slides (you can watch his Mix version &lt;a target="_blank" href="http://channel9.msdn.com/Events/MIX/MIX11/DVC18"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" href="http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WPH309"&gt;Push Notifications at TechEd&lt;/a&gt; (mostly slides); thanks to Thomas Fennel for the original slides and code (you can watch his Mix version &lt;a target="_blank" href="http://channel9.msdn.com/Events/MIX/MIX11/DVC08"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that Jesse Liberty has beaten me to the punch and already posted a &lt;a href="http://wp-7.me/BackStack"&gt;blog entry&lt;/a&gt; based on my first Mix demo (notifications and clearing the back stack).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10167572" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Mix/">Mix</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>"Mango" posts coming soon!</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/04/21/quot-mango-quot-posts-coming-soon.aspx</link><pubDate>Thu, 21 Apr 2011 20:54:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10156850</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10156850</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10156850</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/04/21/quot-mango-quot-posts-coming-soon.aspx#comments</comments><description>&lt;p&gt;Just a quick note - the recorded sessions from Mix are available on &lt;a href="http://channel9.msdn.com/Events/MIX/MIX11?sort=sequential&amp;amp;direction=desc&amp;amp;term=&amp;amp;t=windows%2Bphone"&gt;Channel 9&lt;/a&gt;. I will be posting more on some of the new Mango features soon... still trying to dig out from under the pile of e-mail I received while in Vegas! Also I will get the demo code out to you when the tools are available, if not before (depends on how much "free time" I have to polish it all).&lt;/p&gt;
&lt;p&gt;For those of you who were at Mix (or have seen the videos), maybe &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/12/11/how-to-correctly-handle-application-deactivation-and-reactivation.aspx"&gt;this post&lt;/a&gt; makes more sense now... and maybe also &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/02/23/this-is-not-the-exit-you-are-looking-for.aspx"&gt;this one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10156850" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>I was joking about the penny, but how about some tombstoning sample code?</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/03/21/i-was-joking-about-the-penny-but-how-about-some-tombstoning-sample-code.aspx</link><pubDate>Tue, 22 Mar 2011 02:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10144118</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10144118</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10144118</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/03/21/i-was-joking-about-the-penny-but-how-about-some-tombstoning-sample-code.aspx#comments</comments><description>&lt;p&gt;Thanks to everyone who posted on &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2011/03/06/a-penny-for-your-thoughts-on-tombstoning.aspx"&gt;the previous post about tombstoning&lt;/a&gt; in Windows Phone 7. It was actually quite surprising to see the positive comments about tombstoning (both on the blog and privately through e-mail) where developers are saying they appreciate the feature or don't consider it a huge burden. Of course not everyone thinks that way; tombstoning can be hard to get right if you are porting an existing app from elsewhere and have an app design that doesn't deal well with &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx"&gt;places&lt;/a&gt;, or if you build a complex app and then try and implement tombstoning as an afterthought, or even if your application state is just flat-out complex (like many games) or is hard to recreate in a hurry.&lt;/p&gt;
&lt;p&gt;As to how to do it with the least amount of pain: our general advice is to rely on databinding to bind your UI to a ViewModel, and then serialize your ViewModel into the page state (for transient data) or to Isolated Storage (for permanent data). Of course there are some bugs or "missing features" in our platform that means that not everything works as smoothly as it should. A few examples of things that don't get saved automatically (or do get saved but are hard to restore):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Content of text controls if they have focus at the time of deactivation&lt;/li&gt;
&lt;li&gt;Scroll positions of ListBoxes and ScrollViewers&lt;/li&gt;
&lt;li&gt;Position and state of MediaElement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The project attached to this post serves both as an example of how to use the databinding pattern to save state (for those not familiar with it) and also as a vehicle for a handful of extension methods to help cover the cases above. One thing that is not in the sample project is restoring the focused control or text selection state; I've seen that done in some places but I don't think it is necessary to do this in general; none of the built-in experiences do it as far as I can tell unless those that are almost wholly concerned with text entry (like e-mail compose).&lt;/p&gt;
&lt;p&gt;One thing - the sample project tries to play a media file from &lt;a href="http://localhost"&gt;http://localhost&lt;/a&gt; - you can find it in the ViewModel.cs file - you can replace this with a file of your own choosing hosted on your local PC, or you could put some content into the App package instead.&lt;/p&gt;
&lt;p&gt;I hope you get something out of the attached project, and thanks again for your thoughts. Let me know if there's something else busted!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10144118" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-14-41-18/TombstoningExample_5F00_withUIExtensions.zip" length="152667" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>A penny for your thoughts on Windows Phone 7 tombstoning</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/03/06/a-penny-for-your-thoughts-on-tombstoning.aspx</link><pubDate>Sun, 06 Mar 2011 22:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10137448</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>27</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10137448</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10137448</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/03/06/a-penny-for-your-thoughts-on-tombstoning.aspx#comments</comments><description>&lt;p&gt;One piece of feedback we hear from Windows Phone developers is that &amp;quot;tombstoning is hard,&amp;quot; but there are many ways of interpreting that statement and we'd like to understand it more. We have some theories about what might be hard, but I don't want to skew any results by mentioning them here. &lt;/p&gt;  &lt;p&gt;If you have an opinion on &lt;a href="http://msdn.microsoft.com/en-us/library/ff817008(VS.92).aspx" target="_blank"&gt;tombstoning in Windows Phone 7&lt;/a&gt; - good or bad - please leave a comment and be as detailed as you can in the reply so we can better understand the feedback. &lt;/p&gt;  &lt;p&gt;Thanks!&lt;/p&gt;  &lt;p&gt;P.S. I'm joking about the penny.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10137448" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>This is not the exit you are looking for</title><link>http://blogs.msdn.com/b/ptorr/archive/2011/02/23/this-is-not-the-exit-you-are-looking-for.aspx</link><pubDate>Wed, 23 Feb 2011 16:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10133123</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10133123</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10133123</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2011/02/23/this-is-not-the-exit-you-are-looking-for.aspx#comments</comments><description>&lt;p&gt;[Update 7/27: &lt;span style="color: #ff6600;"&gt;fixed a typo&lt;/span&gt; and made it a bit clearer; thanks Nicole! Also &lt;span style="color: #008000;"&gt;added a link to code with the new Mango APIs&lt;/span&gt;]&lt;/p&gt;
&lt;p&gt;I have previously blogged about &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/01/exiting-a-windows-phone-application.aspx" target="_blank"&gt;exiting a Windows Phone application&lt;/a&gt; but a further post is needed due to a disturbing trend we're seeing in the marketplace: more and more applications are choosing to throw an unhandled exception in order to exit themselves.&lt;/p&gt;
&lt;p&gt;There appear to be several reasons for this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The application has some kind of consent screen and if the user says "No" they want to quit&lt;/li&gt;
&lt;li&gt;The application has a complex navigation system and the only way to quit when hitting the Back key is to force-quit&lt;/li&gt;
&lt;li&gt;The application receives an error response from a webservice and doesn't want to handle it&lt;/li&gt;
&lt;li&gt;The application really wants an "Exit" button&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The recommended way to handle #1 is covered in the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/01/exiting-a-windows-phone-application.aspx" target="_blank"&gt;previous post&lt;/a&gt;: just omit the "No" button and the user will figure out that &lt;span style="color: #ff6600;"&gt;pressing the &lt;/span&gt;&lt;span style="color: #ff6600;"&gt;Start or Back buttons both have the desired result of removinf the application from the screen&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The recommended way to handle #2 for most applications is covered in my &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx" target="_blank"&gt;places post&lt;/a&gt; (now on &lt;a href="http://msdn.microsoft.com/en-us/library/gg278407(VS.92).aspx" target="_blank"&gt;MSDN&lt;/a&gt;): when used correctly, page-based navigations will enable the user to back out naturally. For some applications that have a strong focus on "browsing" content - like the IMDb or Amazon applications, for example - the "places" concept doesn't really fit, and &lt;a href="http://windowsteamblog.com/members/yochay-kiriaty/" target="_blank"&gt;Yochay&lt;/a&gt; has published a recipe for a &lt;a href="http://create.msdn.com/en-us/education/catalog/article/nln-serv-wp7" target="_blank"&gt;non-linear navigation service&lt;/a&gt; that should handle most cases of returning correctly to a home screen such that the Back button naturally exits your application.&lt;/p&gt;
&lt;p&gt;The recommended way to handle #3 is to deal with the failure and let the user know something went wrong. Exceptions are meant for "exceptional" (ie, unexpected) situations, and having a web service call return an error code is &lt;span style="text-decoration: underline;"&gt;not&lt;/span&gt; an unexpected situation. It is a terrible user experience to be interacting with an application and then suddenly see it disappear and be dumped unceremoniously at the Start menu. Obviously we don't want applications showing the HTTP error code to the user, but a simple piece of UX like "request failed; try again?" would suffice. Even if your app is totally unusable without the web service connection, you can at least show some UX along the lines of "we can't connect right now; try again later" and leave it to the user to hit Back or Start.&lt;/p&gt;
&lt;p&gt;The recommended way to handle #4 is to embrace the Windows Phone UX and realize that an Exit button is superfluous. One explanation for why developers want to have an Exit option goes along the lines of this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The phone has limited resources. If the user is done with my app, I want to be a good citizen and stop using resources. On other platforms (Windows Mobile, Windows Desktop, some other mobile OSes) simply switching away from an application doesn't kill it. Therefore I will let the user completely exit my app to ensure I don't use their phone's resources.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The thing is, on Windows Phone 7 the OS does take care of deactivating your application so that it can't use precious resources like CPU, memory, or battery. If the user hits Start to begin another task, your app is gone and can't possibly affect the user experience; there is no need to explicitly exit it. Furthermore, if some applications start having Exit buttons and others don't, there is a fear that customers will start to look for exit buttons everywhere. The logic goes something like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This app has an Exit button&lt;/li&gt;
&lt;li&gt;I know I can just hit the power button to put the phone to sleep, or hit the Start to go to another app, so the Exit button must be there for a reason&lt;/li&gt;
&lt;li&gt;The reason is probably that the app will drain my battery if I don't exit it (based on past experience, urban legend, etc.)&lt;/li&gt;
&lt;li&gt;I'd better start exiting all my apps to ensure my battery doesn't drain too fast&lt;/li&gt;
&lt;li&gt;Oh my goodness, most apps don't have Exit buttons&lt;/li&gt;
&lt;li&gt;Panic!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;We don't want to burden our users with the fear of wasting resources and the need to exit apps&lt;/em&gt;; we just want them to love using the phone. Putting an Exit button in your app just confuses users and reduces their overall satisfaction with the phone. That's the theory, anyway :-).&lt;/p&gt;
&lt;p&gt;Another problem with deliberately crashing your application (vs. relying on the user to hit Start) is that the application will be removed from the back stack, breaking the user's expectation that they can return to it using the Back button. This will only get worse in the future, as users will expect recently-used applications to be in the application-switching UI (as &lt;a href="http://www.microsoft.com/presspass/presskits/windowsphone/videoGallery.aspx" target="_blank"&gt;demoed at Mobile World Congress&lt;/a&gt;), but applications that crash due to an unhandled exception won't appear in that list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-small;" size="2"&gt;Certification Requirements&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://go.microsoft.com/?linkid=9730558" target="_blank"&gt;Application Certification Requirements&lt;/a&gt; have two things to say on this topic.&lt;/p&gt;
&lt;p&gt;Firstly, requirement 5.2.4(a) states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Pressing the Back button from the first screen of an application must exit the application&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is most likely what drives #2 above - the app needs to pass certification testing, but due to their complex back stack the Back button doesn't actually exit the app. Ideally the requirement would add "&lt;em&gt;...without resorting to throwing an exception&lt;/em&gt;" to make it clear this should happen naturally, but currently it doesn't. Fixing the navigation pattern will let you pass certification without throwing exceptions.&lt;/p&gt;
&lt;p&gt;Secondly, requirement 5.1.2 states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The application must handle exceptions raised by the .NET Framework and not terminate unexpectedly. [...] An application that terminates unexpectedly fails certification. &lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This requirement is enforced for normal application usage - if the application crashes randomly during testing, it will fail - but is not currently being tested for the exit case because in some ways the termination is not "unexpected" - the user pressed Back and the app disappeared. Nevertheless, this is not the spirit of the requirement and you shouldn't take advantage of it.&lt;/p&gt;
&lt;p&gt;Requirement 5.1.2 also states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;When handling exceptions, an application must provide a user-friendly error message. You may present a message that is relevant to the context of the application. The application must continue to run and remain responsive to user input after the exception is handled. &lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This clearly shows that scenario #3 above (exiting when an exception is received) violates the certification requirements and should not happen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-small;" size="2"&gt;Future Developments&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The current situation isn't ideal - we have an API set that doesn't meet everyone's needs (although Yochay's sample goes a long way to solving many problems) and we have certification requirements that aren't crystal clear (or always enforced). &lt;span style="text-decoration: line-through;"&gt;Obviously I can't promise you anything about future updates, but we are thinking about these things and trying to improve them at all levels (APIs, certification, documentation, etc.). Your best bet is probably to wait for Mix '11 in April, but &lt;a href="http://live.visitmix.com/news/windows-phone-and-silverlight-chiefs-return-for-mix11" target="_blank"&gt;other than the keynote&lt;/a&gt; nothing has been announced yet so don't hold your breath for Joe Belfiore to mention exit buttons on-stage ;-).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #008000;"&gt;I can now revearl that there are some new APIs in Mango to specifically deal with his - see my post on &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2011/05/28/alarms-and-notifications-in-mango.aspx"&gt;&lt;span style="color: #008000;"&gt;Alarms and Notifications&lt;/span&gt;&lt;/a&gt; for some sample code for dealing with "interesting" navigation scenarios.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-small;" size="2"&gt;What about XNA?&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An observant developer might point out that XNA applications on the phone do have access to an Exit method, so doesn't that invalidate everything I said above? Yes and no: Yes, XNA applications can exit themselves; No, XNA applications can't not exit themselves (with apologies to &lt;a href="http://www.nbc.com/30-rock/bios/alec_baldwin.shtml" target="_blank"&gt;Jack Donaghy&lt;/a&gt;). But seriously, this is more about compatibility with the other XNA platforms (Windows and Xbox) that use the Back button on a controller to show menus or exit. Additionally, the only game I have seen that actually uses this feature is Tetris; that's not to say other games don't use it, but it's clearly not used universally by XNA applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-small;" size="2"&gt;Feedback&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Feel free to add a comment below (or send me a private mail) if you have other reasons for needing to exit your application; please be as descriptive as possible as to what your intended UX is and why you can't build that with the current API set. All feedback is helpful!&lt;/p&gt;
&lt;p&gt;Thanks to Steve Bell and other Windows Phone folks for their input on this blog post.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10133123" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>How to correctly handle application deactivation and reactivation</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/12/11/how-to-correctly-handle-application-deactivation-and-reactivation.aspx</link><pubDate>Sat, 11 Dec 2010 20:40:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10103639</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10103639</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10103639</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/12/11/how-to-correctly-handle-application-deactivation-and-reactivation.aspx#comments</comments><description>&lt;p&gt;Much has been written about tombstoning and how important it is that your application be able to save and restore state once it goes into the background. This is all good.&lt;/p&gt;  &lt;p&gt;One of the finer points of the Windows Phone application model that has received less attention is the case where your application moves into the background and does &lt;em&gt;not &lt;/em&gt;get tombstoned. In the current implementation of the Windows Phone operating system, there are two cases where your application will be deactivated but not tombstoned:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;When calling certain launchers and choosers, the system attempts to keep your process alive in order to give a seamless Back experience for the user&lt;/li&gt;    &lt;li&gt;If the user accidentally leaves your app (eg, via the Start or Search buttons) and immediately hits Back to return to your application &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Most developers are familiar with the first case because it is a core part of application development. Many developers, however, are not familiar with the second case because it's something you don't typically encounter during normal development and testing. Let's look at the different sequence of events that happen in the tombstone case and the non-tombstone case:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Tombstone Case (typical)&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Current page gets &lt;strong&gt;OnNavigatedFrom&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Application gets &lt;strong&gt;Deactivated&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Process dies&lt;/li&gt;    &lt;li&gt;Process starts&lt;/li&gt;    &lt;li&gt;Application gets constructed&lt;/li&gt;    &lt;li&gt;Application gets &lt;strong&gt;Activated&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Current page gets constructed&lt;/li&gt;    &lt;li&gt;Current page gets &lt;strong&gt;OnNavigatedTo&lt;/strong&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Non-Tombstone Case (Start -&amp;gt; Back)&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Current page gets &lt;strong&gt;OnNavigatedFrom&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Application gets &lt;strong&gt;Deactivated&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Application gets &lt;strong&gt;Activated&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Current page gets &lt;strong&gt;OnNavigatedTo&lt;/strong&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;See what's missing? That's right, &lt;u&gt;none of your constructors get called&lt;/u&gt; in the non-tombstone case, because they were never removed from memory. To see this in action, try the following:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Create a default Windows Phone application in VS&lt;/li&gt;    &lt;li&gt;Add the following line inside the &lt;strong&gt;App&lt;/strong&gt; class (right after the declaration of &lt;strong&gt;RootFrame&lt;/strong&gt;):      &lt;br /&gt;      &lt;br /&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#0000ff"&gt;public static &lt;/font&gt;&lt;font color="#4bacc6"&gt;GeoCoordinateWatcher&lt;/font&gt; GCW = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#4bacc6"&gt;GeoCoordinateWatcher&lt;/font&gt;();&lt;/font&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Add the following lines inside the &lt;strong&gt;Deactivate &lt;/strong&gt;handler (because you want to be a good citizen and clean-up after yourself)      &lt;br /&gt;      &lt;br /&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt; (GCW != &lt;font color="#0000ff"&gt;null&lt;/font&gt;)        &lt;br /&gt;&amp;#160; GCW.Stop();&lt;/font&gt;&lt;/li&gt;    &lt;/ol&gt;&lt;p&gt;&lt;font size="2" face="Courier New"&gt;GCW = &lt;font color="#0000ff"&gt;null&lt;/font&gt;;        &lt;br /&gt;&lt;/font&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;ul&gt;&lt;li&gt;And a &lt;strong&gt;Button&lt;/strong&gt; to &lt;strong&gt;MainPage&lt;/strong&gt; and put the following line inside the &lt;strong&gt;Click &lt;/strong&gt;handler:      &lt;br /&gt;      &lt;br /&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#4bacc6"&gt;App&lt;/font&gt;.GCW.Start();&lt;/font&gt;&lt;/li&gt;   &lt;/ul&gt;&lt;p&gt;Now run the application and click the button. Nothing should happen (which is fine).&lt;/p&gt;  &lt;p&gt;Now hit the Start key &lt;em&gt;immediately &lt;/em&gt;followed by the Back key, and try clicking the button again. If you are lucky, nothing will happen (same as before) but if you are unlucky the application will crash and you will be returned to the Start menu. If you are having trouble reproducing the problem, add the following line to your &lt;strong&gt;Deactivated &lt;/strong&gt;handler to simulate the application doing some work during deactivation, such as saving data to IsoStore:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#4bacc6"&gt;Thread&lt;/font&gt;.Sleep(2000);&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;By looking at the sequence of events above for the non-tombstone case, it should be obvious why the application is crashing - &lt;strong&gt;GCW&lt;/strong&gt; is implicitly created in the application's static constructor (by virtue of it being a field initializer), but it is destroyed in the &lt;strong&gt;Deactivated &lt;/strong&gt;event. Since the application is then re-activated without being re-constructed, &lt;strong&gt;GCW &lt;/strong&gt;remains &lt;strong&gt;null &lt;/strong&gt;and the call to &lt;strong&gt;Start()&lt;/strong&gt; will fail.&lt;/p&gt;  &lt;p&gt;In order to fix the problem, we simply recreate &lt;strong&gt;GCW&lt;/strong&gt; in the &lt;strong&gt;Activated &lt;/strong&gt;event, and now all is fine:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font size="2" face="Courier New"&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt; (GCW == &lt;font color="#0000ff"&gt;null&lt;/font&gt;)        &lt;br /&gt;&amp;#160; GCW = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#4bacc6"&gt;GeoCoordinateWatcher&lt;/font&gt;();&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Another approach would be to remove the field initializer altogether, and to unconditionally construct the object in both the &lt;strong&gt;Launching &lt;/strong&gt;and &lt;strong&gt;Activated &lt;/strong&gt;events (possibly via a shared initialization routine). Of course performance best-practices would say to do none of this but to lazily create the object only when it is first needed, but that makes the example harder ;-). The point is that you don't have to undo everything in the activated event - you can be lazy - but you must ensure that your application can cope with being reactivated without being tombstoned. A similar sequence of events can occur for your pages, where they receive &lt;strong&gt;OnNavigatedFrom &lt;/strong&gt;followed by the &lt;strong&gt;OnNavigatedTo &lt;/strong&gt;without being destroyed and re-constructed in the meantime.&lt;/p&gt;  &lt;p&gt;Note that this behaviour is covered in &lt;a href="http://msdn.microsoft.com/en-us/library/ff817008(VS.92).aspx" target="_blank"&gt;the existing Windows Phone documentation&lt;/a&gt;, but not everybody reads the docs (which is unfortunate). Please read the documentation :-)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10103639" width="1" height="1"&gt;</description></item><item><title>That memory thing I promised you</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/10/30/that-memory-thing-i-promised-you.aspx</link><pubDate>Sat, 30 Oct 2010 07:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10083395</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10083395</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10083395</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/10/30/that-memory-thing-i-promised-you.aspx#comments</comments><description>&lt;p&gt;Today &lt;a target="_blank" href="http://www.jeff.wilcox.name/blog/"&gt;Jeff Wilcox&lt;/a&gt;, &lt;a target="_blank" href="http://blogs.msdn.com/b/delay/"&gt;David Anson&lt;/a&gt;, and I did a &lt;a target="_blank" href="http://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt; live session with Dan Fernandez at the PDC on Microsoft campus. You can catch it almost exactly 55 minutes into the stream &lt;a target="_blank" href="http://bit.ly/9UUvD1"&gt;here&lt;/a&gt; (note to self: try to remember what team you work on - it's the &lt;em&gt;Application Platform&lt;/em&gt; team, not the &lt;em&gt;Application Development&lt;/em&gt; team!)&lt;/p&gt;
&lt;p&gt;One thing I mentioned was the LazyListBox, which you can find &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/10/12/procrastination-ftw-lazylistbox-should-improve-your-scrolling-performance-and-responsiveness.aspx"&gt;here&lt;/a&gt;, and the other ListBox virtualization samples that you can find on the Silverlight Performance blog &lt;a target="_blank" href="http://blogs.msdn.com/b/slmperf/archive/2010/10/06/silverlight-for-windows-phone-7-listbox-scroll-performance.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, I foolishly promised to publish something on my blog, so here it is. It's a simple class called &lt;strong&gt;MemoryDiagnosticsHelper&lt;/strong&gt; that shows a counter similar to the built-in frame-rate counter that can be used to show how much memory you are using. It will also &lt;strong&gt;Assert &lt;/strong&gt;if you go over the &lt;a href="http://go.microsoft.com/fwlink/?LinkID=183220"&gt;marketplace limit&lt;/a&gt; of 90MB, which is nice. It also ensures that the calls to &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.deviceextendedproperties(VS.92).aspx"&gt;DeviceExtendedProperties&lt;/a&gt; are only made in &lt;strong&gt;DEBUG&lt;/strong&gt; mode so that you won't get a scary disclosure in marketplace for &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.phone.info.deviceextendedproperties.getvalue(VS.92).aspx"&gt;"identifying the device."&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyway, the code is attached along with a very silly sample app. All you really need is the &lt;strong&gt;MemoryDiagnosticsHelper.cs&lt;/strong&gt; file though, which you can pull into your existing apps and add a line like this in &lt;strong&gt;App.xaml.cs&lt;/strong&gt; right under the call to &lt;strong&gt;EnableFrameRateCounter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MemoryDiagnosticsHelper.Start(TimeSpan.FromMilliseconds(500), true);&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10083395" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-08-33-95/MemoryDiagnosticApp.zip" length="20371" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Procrastination FTW - LazyListBox Should Improve your Scrolling Performance and Responsiveness</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/10/12/procrastination-ftw-lazylistbox-should-improve-your-scrolling-performance-and-responsiveness.aspx</link><pubDate>Tue, 12 Oct 2010 09:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10074614</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10074614</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10074614</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/10/12/procrastination-ftw-lazylistbox-should-improve-your-scrolling-performance-and-responsiveness.aspx#comments</comments><description>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;One of the things I've been working on for a while is a "smart" ListBox implementation that uses the new &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/07/23/how-to-detect-when-a-list-is-scrolling-or-not.aspx"&gt;scrolling states&lt;/a&gt; and &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx"&gt;data virtualization&lt;/a&gt; features in Windows Phone 7 to help improve performance. Here's a relatively common pattern we see with developers who are new to Silverlight (or just new to the phone):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get a very large dataset of complex objects, possibly coming from a web request &lt;/li&gt;
&lt;li&gt;Bind it to a &lt;strong&gt;ListBox &lt;/strong&gt;with a complex &lt;strong&gt;ItemTemplate &lt;/strong&gt;that has an expensive layout, often including images &lt;/li&gt;
&lt;li&gt;Witness an unresponsive / glitchy application during page-load or while scrolling&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sometimes Step 3 isn't as noticeable on the emulator because it is very fast on a powerful desktop computer, but on the resource-constrained phone you are more likely to see issues with performance and responsiveness when binding large, complex lists. This post includes a sample application that shows three different ways of binding to data from the &lt;a target="_blank" href="http://developer.netflix.com/docs/oData_Catalog"&gt;Netflix OData service&lt;/a&gt; (which is very cool, by the way!) and how each improves on the former.&lt;/p&gt;
&lt;p&gt;The first part of the problem (binding to a large dataset) can be mitigated by using &lt;strong&gt;IList&lt;/strong&gt; instead of &lt;strong&gt;IEnumerable&lt;/strong&gt;, as discussed in my &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx"&gt;data virtualization posting&lt;/a&gt; and in Shawn's &lt;a target="_blank" href="http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx"&gt;eerily-similar post&lt;/a&gt;. The next part of the problem - what to do about those expensive &lt;strong&gt;ItemTemplates&lt;/strong&gt; and the other heavy lifting that is required to actually show your items - is what this post is focused on mitigating. You should also read the &lt;a target="_blank" href="http://blogs.msdn.com/b/slmperf/archive/2010/10/06/silverlight-for-windows-phone-7-listbox-scroll-performance.aspx"&gt;recently-posted article on ListBox performance&lt;/a&gt; over at the newly-minted &lt;em&gt;Silverlight for Windows Phone Performance team blog&lt;/em&gt;.&lt;/p&gt;
&lt;h1&gt;A Three-Step Solution&lt;/h1&gt;
&lt;p&gt;The solution outlined in this post has three parts to it, each of which I'll discuss in turn. They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using the scrolling state to avoid doing work while the list is scrolling &lt;/li&gt;
&lt;li&gt;Using different &lt;strong&gt;DataTemplates &lt;/strong&gt;for your items, depending on whether they are actually on-screen or not &lt;/li&gt;
&lt;li&gt;Using an explicit state machine for controlling the work done by items depending on whether they are visible or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's look at each in turn, although they are all related.&lt;/p&gt;
&lt;h2&gt;Don't do work while the user is scrolling&lt;/h2&gt;
&lt;p&gt;The first part of the solution is to use the scroll-states exposed by the &lt;strong&gt;ScrollViewer &lt;/strong&gt;in Windows Phone to detect when the list is scrolling and when it has stopped scrolling. There are two reasons for doing this. The first is that you want to &lt;em&gt;avoid doing any work on the UI thread while the list is being scrolled&lt;/em&gt;, otherwise it won't be responsive to the user's gestures or you might see blank items in your list if the UI thread (which is creating the content for the items) can't keep up with the render thread (which is animating them). The other is that you want to&amp;nbsp;&lt;em&gt;avoid doing any work for items that are not visible to the user &lt;/em&gt;(see the next section) but the computation for what is visible and what is not visible is expensive, and per the previous sentence we don't want to do that expensive work while the list is scrolling. So we need to wait for the list to stop scrolling before we can compute the visible items.&lt;/p&gt;
&lt;h3&gt;The IsScrolling property and ScrollingStateChanged event&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;LazyListBox &lt;/strong&gt;exposes a &lt;strong&gt;DependencyProperty &lt;/strong&gt;named &lt;strong&gt;IsScrolling &lt;/strong&gt;that will tell you whether or not the list is scrolling; you can databind to it if you like, for example to show or hide some other UI in your application. It also exposes a &lt;strong&gt;ScrollingStateChanged &lt;/strong&gt;event that you can hook to do other work when the state changes. The property and the event are synthesized by hooking the &lt;strong&gt;VisualStateGroup.CurrentStateChanging&lt;/strong&gt; event of the underlying &lt;strong&gt;ScrollViewer&lt;/strong&gt;, as outlined in my &lt;a target="_blank" href="http://blogs.msdn.com/b/ptorr/archive/2010/07/23/how-to-detect-when-a-list-is-scrolling-or-not.aspx"&gt;previous blog post&lt;/a&gt; on the topic. Internally, the &lt;strong&gt;LazyListBox &lt;/strong&gt;also uses the scrolling start notification to alert the items in the list that they should "Pause" any work they are currently doing, and it uses the stop notification to compute the visible items in the list. &lt;/p&gt;
&lt;h3&gt;The OnListChangesComplete method&lt;/h3&gt;
&lt;p&gt;The most interesting code in the sample is probably &lt;strong&gt;LazyListBox.OnListChangesComplete &lt;/strong&gt;and the functions that it calls. In particular, it uses some extension methods and some LINQ magic to check which items are visible in the list using the extension method &lt;strong&gt;ExtensionMethods.GetVisibleItems&amp;lt;T&amp;gt;()&lt;/strong&gt;. This method in turn ends up calling &lt;strong&gt;TestVisibility &lt;/strong&gt;for each of the virtualized items in the list (which is expensive, which is why it only happens when you stop scrolling). Basically the whole reason I need to detect list scrolling state is so that I can avoid calling OnListChangesComplete unless I know that the list changes (and animations) are, well, complete.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TestVisibility&lt;/strong&gt; is the "expensive" work-horse, and it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #0000ff;"&gt;public static bool&lt;/span&gt; TestVisibility(&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt; &lt;span style="color: #4f81bd;"&gt;FrameworkElement&lt;/span&gt; item, &lt;span style="color: #4f81bd;"&gt;FrameworkElement&lt;/span&gt; viewport, &lt;span style="color: #4f81bd;"&gt;Orientation&lt;/span&gt; orientation, &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; wantVisible) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #008040;"&gt;// Determine the bounding box of the item relative to the viewport &lt;br /&gt;&lt;/span&gt;&amp;nbsp; &lt;span style="color: #4f81bd;"&gt;GeneralTransform&lt;/span&gt; transform = item.TransformToVisual(viewport); &lt;br /&gt;&amp;nbsp; &lt;span style="color: #4f81bd;"&gt;Point&lt;/span&gt; topLeft = transform.Transform(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #4f81bd;"&gt;Point&lt;/span&gt;(0, 0)); &lt;br /&gt;&amp;nbsp; &lt;span style="color: #4f81bd;"&gt;Point&lt;/span&gt; bottomRight = transform.Transform(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;span style="color: #4f81bd;"&gt;Point&lt;/span&gt;(item.ActualWidth, item.ActualHeight));&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #008040;"&gt;// Check for overlapping bounding box of the item vs. the viewport, depending on orientation &lt;br /&gt;&lt;/span&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt; min, max, testMin, testMax; &lt;br /&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (orientation == &lt;span style="color: #4f81bd;"&gt;Orientation&lt;/span&gt;.Vertical) &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; min = topLeft.Y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; max = bottomRight.Y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testMin = 0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testMax = &lt;span style="color: #4f81bd;"&gt;Math&lt;/span&gt;.Min(viewport.ActualHeight, &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;.IsNaN(viewport.Height) ? &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;.PositiveInfinity : viewport.Height); &lt;br /&gt;&amp;nbsp; } &lt;br /&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; min = topLeft.X; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; max = bottomRight.X; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testMin = 0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; testMax = &lt;span style="color: #4f81bd;"&gt;Math&lt;/span&gt;.Min(viewport.ActualWidth, &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;.IsNaN(viewport.Width) ? &lt;span style="color: #0000ff;"&gt;double&lt;/span&gt;.PositiveInfinity : viewport.Width); &lt;br /&gt;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; result = wantVisible;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp; if (min &amp;gt;= testMax || max &amp;lt;= testMin) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = !wantVisible;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; result; &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In theory this method could be sped up by accumulating the maximum Y (or X) value and then assuming that each subsequent item is directly below (to the right of) the previous item, but that didn't seem worth the extra effort.&lt;/p&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h2&gt;Don't compute complex layouts if the items aren't on-screen&lt;/h2&gt;
&lt;p&gt;Once we know which items are on-screen and which items are not, we can do interesting things like only show complex &lt;strong&gt;DataTemplates &lt;/strong&gt;for the items the user can see. Then we don't pay the cost of databinding and laying out all the items that you can't see anyway. In the sample, I use three different &lt;strong&gt;DataTemplates &lt;/strong&gt;for the &lt;strong&gt;LazyListBoxItem &lt;/strong&gt;container (which are set via the &lt;strong&gt;LazyListBox &lt;/strong&gt;properties):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;ItemTemplate&lt;/strong&gt;. This is the normal template that is exposed by ListBox and is used by default for all items in the list when they are not on-screen. This should be a very simple template that databinds only the bare minimum of data (if any!) and doesn't have a complex layout&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LoadedItemTemplate&lt;/strong&gt;. This is a new template that is used only when items are on-screen, and this is where you can show the full, rich UI that is databound to various properties and has a complex layout (but not too complex!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CachedItemTemplate&lt;/strong&gt;. This is an "advanced" template used when an item has been previously-visible but is now invisible; it is used only if your items implement &lt;strong&gt;ILazyDataItem &lt;/strong&gt;(see next section)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The selection of which template to use is done in &lt;strong&gt;LazyListBoxItem.SetIsVisible()&lt;/strong&gt;, which is a function that &lt;strong&gt;OnListChangesComplete &lt;/strong&gt;ends up calling for all the virtualized items in the list to let them know if they are currently visible or not.&amp;nbsp; &lt;/p&gt;
&lt;h3&gt;Animating data into view&lt;/h3&gt;
&lt;p&gt;Using &lt;strong&gt;LoadedItemTemplate &lt;/strong&gt;along with some animations can lead to some nice effects, like the one used in the Netflix sample project. If you haven't run the project yet, the &lt;strong&gt;ItemTemplate&lt;/strong&gt; looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img height="306" width="493" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/4111.netflix_5F00_itemtemplate_5F00_44013E41.jpg" alt="netflix_itemtemplate" border="0" title="netflix_itemtemplate" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 30px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/p&gt;
&lt;p&gt;And the &lt;strong&gt;LoadedItemTemplate&lt;/strong&gt; looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img height="306" width="493" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/6354.netflix_5F00_loadeditemtemplate_5F00_13F6ECC0.jpg" alt="netflix_loadeditemtemplate" border="0" title="netflix_loadeditemtemplate" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 30px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/p&gt;
&lt;p&gt;The app plays a simple fade animation between the two of them when the list comes to a halt - here's the XAML, with the interesting bits highlighted (I wish copying colour-coded text from VS worked correctly... I manually formatted the code above, but XML is just too hard to format by hand):&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-size: small;"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Courier New; font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;lazy:LazyListBox x:Name="MainListBox" Margin="0,0,-12,0" Opacity="0.3" ItemsSource="{Binding Data}"&amp;gt; &lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;&amp;lt;lazy:LazyListBox.ItemTemplate&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DataTemplate&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;Border Height="100"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Title}" Style='{StaticResource PhoneTextLargeStyle}' Margin='112,1,12,0' Grid.Column='1' VerticalAlignment='Center' /&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Border&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DataTemplate&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/lazy:LazyListBox.ItemTemplate&amp;gt; &lt;br /&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #800040;"&gt;&lt;span style="font-size: small;"&gt; &amp;lt;lazy:LazyListBox.LoadedItemTemplate&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DataTemplate&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid Height="100"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid.Triggers&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--Show a nice animation to fade the minimal content into the full content--&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #008040;"&gt;&amp;lt;EventTrigger RoutedEvent="Grid.Loaded"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;BeginStoryboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;BeginStoryboard.Storyboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Storyboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DoubleAnimation Storyboard.TargetName="largeText" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:0.6"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DoubleAnimation.EasingFunction&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PowerEase EasingMode="EaseIn" Power="3"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DoubleAnimation.EasingFunction&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DoubleAnimation&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DoubleAnimation Storyboard.TargetName="details" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.6"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DoubleAnimation.EasingFunction&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PowerEase EasingMode="EaseOut" Power="3"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DoubleAnimation.EasingFunction&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DoubleAnimation&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Storyboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/BeginStoryboard.Storyboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/BeginStoryboard&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/EventTrigger&amp;gt; &lt;br /&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid.Triggers&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color: #800040;"&gt;&lt;span style="font-size: small;"&gt;&amp;lt;Grid.ColumnDefinitions&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ColumnDefinition Width="100"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ColumnDefinition Width="*"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid.ColumnDefinitions&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Image Source="{Binding ImageSource}" Grid.Column="0" Stretch="Uniform" Width="65" Height="90" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="12,0"/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock x:Name="largeText" Grid.Column="1" Text="{Binding Title}" Style='{StaticResource PhoneTextLargeStyle}' VerticalAlignment='Center'/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StackPanel Margin="1,4,0,0" Grid.Column="1" x:Name="details" Height="80" VerticalAlignment="Top"&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Title}" Style='{StaticResource PhoneTextNormalStyle}' Height='27'/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Description}" TextWrapping="Wrap" Height="53" FontSize="{StaticResource PhoneFontSizeSmall}" Style='{StaticResource PhoneTextSubtleStyle}'/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/StackPanel&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DataTemplate&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="color: #800040;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/lazy:LazyListBox.LoadedItemTemplate&amp;gt; &lt;br /&gt;&lt;/span&gt;&amp;lt;/lazy:LazyListBox&amp;gt; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It's pretty straight-forward stuff - the blue text is the simple &lt;strong&gt;ItemTemplate&lt;/strong&gt;, the maroon stuff is the &lt;strong&gt;LoadedItemTemplate&lt;/strong&gt;, and the green stuff is the (one and only) supported &lt;strong&gt;Trigger &lt;/strong&gt;in Silverlight that I am using to do the fade-in animation (you could use the &lt;strong&gt;ControlStoryboardAction &lt;/strong&gt;from Blend instead if you liked). Note that my &lt;strong&gt;ItemTemplate &lt;/strong&gt;is very simple and consists of just a &lt;strong&gt;TextBlock &lt;/strong&gt;inside a &lt;strong&gt;Border&lt;/strong&gt;, whereas the &lt;strong&gt;LoadedItemTemplate &lt;/strong&gt;contains a &lt;strong&gt;Grid &lt;/strong&gt;with two columns, an &lt;strong&gt;Image&lt;/strong&gt;, three &lt;strong&gt;TextBlocks&lt;/strong&gt;, and an animation.&lt;/p&gt;
&lt;p&gt;The net effect is that when you're scrolling the list you see the nice big title text (and nothing else), and when you stop it fades away to show you the full details including the picture. Not only does this aid with performance, but it also makes the list contents more readable as you are scrolling because the text is larger. Neat,huh?&lt;/p&gt;
&lt;h2&gt;Delay all work until the last-possible minute&lt;/h2&gt;
&lt;p&gt;The final thing we do is to not do any work at all! The system tries to avoid doing work whenever it doesn't need to, and you can also participate in this lazy behaviour if you implement the &lt;strong&gt;ILazyDataItem &lt;/strong&gt;interface on your items that are added to the list.&lt;/p&gt;
&lt;h3&gt;ILazyDataItem interface&lt;/h3&gt;
&lt;p&gt;This interface is used to implement a state machine that models the various states a "heavy" object can be in. It models the data loaded into the object on two independency axes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The speed with which the data can be retrieved (synchronous or asynchronous)&lt;/li&gt;
&lt;li&gt;The size of the data (basically "small strings" or "large objects")&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the &lt;strong&gt;LazyListBoxItem &lt;/strong&gt;class is home to one of these objects, it will use it and follow the state machine below (click to enlarge):&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/5277.statemachine_5F00_287C3C3E.jpg"&gt;&lt;img height="397" width="540" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/4617.statemachine_5F00_thumb_5F00_4BC930E3.jpg" alt="statemachine" border="0" title="statemachine" style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px 0px 0px 30px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It looks complicated ;-) but it's actually quite simple. The common state transitions are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unloaded -&amp;gt; Minimum&lt;/strong&gt;. You load the bare minimum content to display something on the screen (to match your &lt;strong&gt;ItemTemplate&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minimum -&amp;gt; Loading&lt;/strong&gt;. Time to start loading all the data for your item (to match your &lt;strong&gt;LoadedItemTemplate&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loading -&amp;gt; Loaded&lt;/strong&gt;. You have finished loading your items (this is a transition driven by you, not by &lt;strong&gt;LazyListBoxItem&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loaded -&amp;gt; Cached&lt;/strong&gt;. You were loaded, but now you're off-screen and should dump any memory-hogging data (to match your &lt;strong&gt;CachedItemTemplate&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also a &lt;strong&gt;Reloading &lt;/strong&gt;state which is just a special case of &lt;strong&gt;Loading &lt;/strong&gt;(when you already have some data loaded), and you can optionally support a &lt;strong&gt;Pause &lt;/strong&gt;/ &lt;strong&gt;UnPause &lt;/strong&gt;operation to stop doing work while the list is scrolling.&lt;/p&gt;
&lt;p&gt;In the interests of time, I did not implement &lt;strong&gt;ILazyDataItem &lt;/strong&gt;in the Netflix demo (otherwise I would never have gotten this post out!) but it is used by the dummy data item in the &lt;strong&gt;DelayLoadListBoxItem &lt;/strong&gt;project.&lt;/p&gt;
&lt;h2&gt;Other miscellaneous stuff&lt;/h2&gt;
&lt;p&gt;The project has some other things in it, like remembering the scroll position of a list during tombstoning (using the extension method &lt;strong&gt;SetVerticalScrollOffset&lt;/strong&gt;) which turned out to be incredibly hard to get right due to the mysterious ways in which events come in, especially when databinding. It took me many, &lt;em&gt;many &lt;/em&gt;hours of trial-and-error debugging and required a custom interface (&lt;strong&gt;ISupportOffsetChanges&lt;/strong&gt;) to implement it correctly and in a way that didn't perform more work than was necessary... I really hope that it actually &lt;em&gt;is&lt;/em&gt; a hard problem (all that work was necessary) vs. it being an obvious thing and I just wasted my time :-).&lt;/p&gt;
&lt;p&gt;That's about it for now - hope you enjoy the code and can use it in your apps. There are several things in the ZIP file attached:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UIExtensionMethods&lt;/strong&gt;. Implements various extension methods for dealing with the visual tree, etc. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LazyListBox&lt;/strong&gt;. Implementation the &lt;strong&gt;LazyListBox&lt;/strong&gt; and &lt;strong&gt;LazyListBoxItem&lt;/strong&gt; classes, and defines the &lt;strong&gt;ILazyDataItem&lt;/strong&gt; interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DelayLoadListBoxItem&lt;/strong&gt;. A test project that implements the &lt;strong&gt;ILazyDataItem &lt;/strong&gt;interface and arbitrarily sucks up memory. More of a testing app that I used while developing the &lt;strong&gt;LazyListBox &lt;/strong&gt;than anything else&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NetflixBrowserTest&lt;/strong&gt;. A test project I build &lt;em&gt;after &lt;/em&gt;writing the &lt;strong&gt;LazyListBox &lt;/strong&gt;to see the real-world difference in performance and to see how hard (or not) it would be to implement a "clean room" application that used the lazy list box.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State Machine for ILazyDataItem&lt;/strong&gt;. A PowerPoint deck that contains the state machine image, above, for your reference&lt;/li&gt;
&lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10074614" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-07-46-14/LazyListBoxBlogPost.zip" length="180402" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>A couple of (late) links</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/09/27/a-couple-of-late-links.aspx</link><pubDate>Mon, 27 Sep 2010 07:53:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10068074</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10068074</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10068074</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/09/27/a-couple-of-late-links.aspx#comments</comments><description>&lt;p&gt;Firstly, fellow WP7 &lt;strike&gt;PM&lt;/strike&gt; Developer Dragos Manolescu is resurrecting his blog and &lt;a href="http://blogs.msdn.com/b/dragoman/archive/tags/wp7/" target="_blank"&gt;posting about Windows Phone 7&lt;/a&gt;. His first WP7 post is a great introductory piece on using Location Services and Reactive LINQ on the phone (and if &lt;a href="http://msdn.microsoft.com/en-us/library/bb397687.aspx" target="_blank"&gt;lambdas&lt;/a&gt; make your brain hurt, don't say I didn't warn you).&lt;/p&gt;  &lt;p&gt;Secondly, the RTM &lt;a href="http://developer.windowsphone.com/windows-phone-7/" target="_blank"&gt;Windows Phone Tools&lt;/a&gt; and the &lt;a href="http://silverlight.codeplex.com/releases/view/52297" target="_blank"&gt;Silverlight for Windows Phone Toolkit&lt;/a&gt; were released the other week (if you didn't already know that, you're probably reading the wrong blog ;-) ).&lt;/p&gt;  &lt;p&gt;Also, in case you weren't already aware of them, here are some other Windows Phone-related blogs you should probably follow:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/delay/"&gt;http://blogs.msdn.com/b/delay/&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/b/devdave/"&gt;http://blogs.msdn.com/b/devdave/&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://shawnoster.com/blog/"&gt;http://shawnoster.com/blog/&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.jeff.wilcox.name/blog/"&gt;http://www.jeff.wilcox.name/blog/&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10068074" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category></item><item><title>Sample code from TechEd New Zealand talks</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/31/sample-code-from-teched-new-zealand-talks.aspx</link><pubDate>Tue, 31 Aug 2010 10:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10056204</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10056204</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10056204</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/31/sample-code-from-teched-new-zealand-talks.aspx#comments</comments><description>&lt;p&gt;&lt;span style="color: #0000ff;"&gt;
&lt;p&gt;&lt;span style="color: #ff6600;"&gt;[Update September 9: Link to the recorded sessions]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;[Update September 2: Updated the ZIP file to comment-out dependency on not-yet-shipped Map control :-)]&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Attached to this post is a ZIP file with three projects in it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Part1Demo&lt;/strong&gt;, which is the demo app for WPH304 &lt;span style="color: #ff6600;"&gt;(video should be available soon at &lt;/span&gt;&lt;a href="http://www.msteched.com/2010/NewZealand/WPH304"&gt;http://www.msteched.com/2010/NewZealand/WPH304&lt;/a&gt;&lt;span style="color: #ff6600;"&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part2Demo&lt;/strong&gt;, which is the demo app for WPH305 &lt;span style="color: #ff6600;"&gt;(video is available at &lt;/span&gt;&lt;a href="http://www.msteched.com/2010/NewZealand/WPH305"&gt;http://www.msteched.com/2010/NewZealand/WPH305&lt;/a&gt;&lt;span style="color: #ff6600;"&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CloudService&lt;/strong&gt;, which is the &amp;ldquo;backend&amp;rdquo; for the push notification section of &lt;strong&gt;Part2Demo&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are the latest revs of the &amp;ldquo;Building WP7 Apps in Silverlight&amp;rdquo; talks that have been given at Mix and TechEd US in the past. They should run on the current beta tools (and not long now until the RTM tools are released!). A lot of the demos use device features so you will not get the full benefit in the emulator. I will also post the &amp;ldquo;no code; all Blend&amp;rdquo; panorama apps in a separate post (they will have to wait until September 16th).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to go into much detail in this post, since I&amp;rsquo;m tired and the apps should pretty much speak for themselves. The code is all quite simple and I have even added some comments! &lt;/p&gt;
&lt;p&gt;One thing you will need to do is provide your own video file for Part 1 (I tried uploading mine but it was too large). It should be called "GoldCoastBeach.wmv" (guess what it was a video of!) or you can simply change the name inside the XAML file if you prefer. The only other tricky bit is in Part 2 where you will need to update the configuration of the service reference to point to your server name instead of &lt;strong&gt;YOUR_SERVER_NAME&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;You will also need to build the &lt;strong&gt;CloudService &lt;/strong&gt;project and deploy it to a web server - this project won&amp;rsquo;t open with the free VPDExpress version of VS, but it&amp;rsquo;s only needed for the push section of the demo and you can run the rest of the demos without it (you also might be able to use one of the other free Express SKUs to do ASP.NET development&amp;hellip;)&lt;/p&gt;
&lt;p&gt;Features shown in Part 1:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;InputScope on TextBox&lt;/li&gt;
&lt;li&gt;Drag and pinch gestures &lt;em&gt;(pinch requires device or multi-touch monitor)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Accelerometer &lt;em&gt;(requires device)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Microphone input &lt;em&gt;(requires device)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;MediaElement control&lt;/li&gt;
&lt;li&gt;WebBrowser control&lt;/li&gt;
&lt;li&gt;Camera capture task&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Features shown in Part 2:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Overriding the back key&lt;/li&gt;
&lt;li&gt;Saving state during tombstoning&lt;/li&gt;
&lt;li&gt;Push notifications &lt;em&gt;(requires the CloudService project)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Location &lt;em&gt;(requires device)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you appreciate the effort I put into the tiles / splash screens, as well! :-)&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10056204" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-05-62-04/TechEdNZDemos.zip" length="494979" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Redirecting an initial navigation</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/28/redirecting-an-initial-navigation.aspx</link><pubDate>Sat, 28 Aug 2010 13:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10055339</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10055339</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10055339</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/28/redirecting-an-initial-navigation.aspx#comments</comments><description>&lt;p&gt;One more post on the subject of keeping screens out of the backstack. A common scenario we see is a variation of the &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/01/exiting-a-windows-phone-application.aspx"&gt;login screen scenario&lt;/a&gt; I mentioned the other week. In this case, the first page the user is supposed to see depends on some state saved in by the application (maybe a user preference for which screen to see first, or maybe based on trial mode, etc.) and whilst you want that first page to be in the back stack (ie, it is a &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx"&gt;legitimate place&lt;/a&gt;) you don&amp;rsquo;t want any additional &amp;ldquo;landing pages&amp;rdquo; taking up a slot in the backstack. Another situation where this arises is if your application is &lt;a href="http://msdn.microsoft.com/en-us/library/ff769558(VS.92).aspx"&gt;extending the Music + Videos hub&lt;/a&gt; or is &lt;a href="http://msdn.microsoft.com/en-us/library/ff402546(VS.92).aspx"&gt;registered as a Photo Extension&lt;/a&gt; and you need to show a different page when launched from these experiences.&lt;/p&gt;
&lt;p&gt;There are (at least) two ways of doing this; I&amp;rsquo;ll present two of them here along with a sample app that shows them in action. For my simple example, the trigger for showing a particular page is going to be whether the current time has an even or odd number of seconds (this is a silly example, but makes it easy to test both startup cases). In a real application the trigger might be based on incoming parameters, settings stored in IsoStore, etc.&lt;/p&gt;
&lt;h2&gt;Cancelling Navigation&lt;/h2&gt;
&lt;p&gt;The first way to change your initial page is to cancel the incoming navigation to MainPage.xaml and then fire off the desired navigation instead. This is easily done in a few lines of code; firstly, at the end of the &lt;strong&gt;App &lt;/strong&gt;constructor we add an event handler to the &lt;strong&gt;Navigating &lt;/strong&gt;event:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp; RootFrame.Navigating += &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; NavigatingCancelEventHandler(RootFrame_Navigating);&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the event handler, we do several things. First, we check if the navigation is to MainPage.xaml (the &lt;strong&gt;NavigationPage &lt;/strong&gt;specified in the WMAppManifest.xml file) and if not, we bail:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; // Only care about MainPage &lt;br /&gt;&lt;/span&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (e.Uri.ToString().Contains(&lt;span style="color: #800040;"&gt;"/MainPage.xaml"&lt;/span&gt;) != &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next we perform a simple check to see which page to load (in this case, are the seconds odd or even?), but this is where you&amp;rsquo;d do your own logic for switching pages:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; // Our dummy check -- does the current time have an odd or even number of seconds? &lt;br /&gt;&lt;/span&gt;&amp;nbsp; DateTime time = DateTime.Now; &lt;br /&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;int&lt;/span&gt; seconds = time.Second; &lt;br /&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt; isOdd = (seconds % 2) == 1;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally we kick off a navigation to the desired page, being careful to avoid overlapping navigations (which will fail):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; // Cancel current navigation and schedule the real navigation for the next tick &lt;br /&gt;&amp;nbsp; // (we can't navigate immediately as that will fail; no overlapping navigations &lt;br /&gt;&amp;nbsp; // are allowed) &lt;br /&gt;&lt;/span&gt;&amp;nbsp; e.Cancel = &lt;span style="color: #0000ff;"&gt;true&lt;/span&gt;; &lt;br /&gt;&amp;nbsp; RootFrame.Dispatcher.BeginInvoke(&lt;span style="color: #0000ff;"&gt;delegate&lt;/span&gt; &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (isOdd) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RootFrame.Navigate(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #800040;"&gt;"/odd.xaml?method=cancel%20navigation&amp;amp;time="&lt;/span&gt; + time.ToLongTimeString(), UriKind.Relative)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RootFrame.Navigate(&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #800040;"&gt;"/even.xaml?method=cancel%20navigation&amp;amp;time="&lt;/span&gt; + time.ToLongTimeString(), UriKind.Relative)); &lt;br /&gt;&amp;nbsp; });&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Using UriMapper&lt;/h2&gt;
&lt;p&gt;The second method you can use is based on the &lt;strong&gt;UriMapper &lt;/strong&gt;class, which is a standard part of the &lt;a href="http://msdn.microsoft.com/en-us/library/cc838245(VS.95).aspx"&gt;Silverlight 3 navigation framework&lt;/a&gt;. &lt;strong&gt;UriMapper &lt;/strong&gt;was slightly easier to use in the Mix-era CTP when we set the &lt;strong&gt;RootVisual &lt;/strong&gt;of the application to a frame inside of App.xaml, but it&amp;rsquo;s still easy to do with the new delayed approach. First of all we add a new &lt;strong&gt;UriMapper &lt;/strong&gt;to the &lt;strong&gt;Resources &lt;/strong&gt;section of App.xaml:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; &amp;lt;!--Simple UriMapper that will be programmatically updated to point to the right page at runtime&amp;mdash;&amp;gt; &lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;lt;UriMapper:UriMapper x:Name=&lt;span style="color: #0000ff;"&gt;"mapper"&lt;/span&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;UriMapper:UriMapping Uri=&lt;span style="color: #0000ff;"&gt;"/MainPage.xaml"&lt;/span&gt; /&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/UriMapper:UriMapper&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then instead of handling the &lt;strong&gt;Navigating&lt;/strong&gt; event (as before), we simply attach the &lt;strong&gt;UriMapper &lt;/strong&gt;to the &lt;strong&gt;RootFrame &amp;hellip;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; // Get the UriMapper from the app.xaml resources, and assign it to the root frame &lt;br /&gt;&lt;/span&gt;&amp;nbsp; UriMapper mapper = Resources[&lt;span style="color: #800040;"&gt;"mapper"&lt;/span&gt;] &lt;span style="color: #0000ff;"&gt;as&lt;/span&gt; UriMapper; &lt;br /&gt;&amp;nbsp; RootFrame.UriMapper = mapper;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and re-write the rule for MainPage based on the desired page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="color: #008000;"&gt;&amp;nbsp; // Update the mapper as appropriate &lt;br /&gt;&lt;/span&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (isOdd) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mapper.UriMappings[0].MappedUri = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #800040;"&gt;"/odd.xaml?method=UriMapper&amp;amp;time="&lt;/span&gt; + time.ToLongTimeString(), UriKind.Relative); &lt;br /&gt;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;else&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mapper.UriMappings[0].MappedUri = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; Uri(&lt;span style="color: #800040;"&gt;"/even.xaml?method=UriMapper&amp;amp;time="&lt;/span&gt; + time.ToLongTimeString(), UriKind.Relative);&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, the code is mostly the same, the difference is whether it is an explicit cancel-then-navigate or whether it is a simple URL-rewrite that happens. If you don&amp;rsquo;t know which one to use, I would recommend the &lt;strong&gt;UriMapper &lt;/strong&gt;solution first (because you can easily extend it for other, non-dynamically-re-mapped scenarios) but it does require that you know what the final URI should be in a synchronous fashion. If for whatever reason you need to perform an asynchronous operation to determine which page to load &amp;ndash; or if you just prefer a 100% code solution &amp;ndash; you can use the &amp;ldquo;cancel navigation&amp;rdquo; approach. Just be sure to navigate within 10 seconds (or include a splash screen) or the system will terminate you for being unresponsive.&lt;/p&gt;
&lt;p&gt;The attached sample lets you pick which approach you want to try by modifying the static &lt;strong&gt;USE_CANCEL_NAVIGATION&lt;/strong&gt; flag set at the top of App.xaml.cs. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10055339" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-05-53-39/RedirectingInitialNavigation.zip" length="18808" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Introducing the concept of “Places”</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx</link><pubDate>Sat, 28 Aug 2010 10:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10055327</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10055327</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10055327</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://australia.msteched.com/default.aspx"&gt;TechEd Australia&lt;/a&gt; is all wrapped up, and I wanted to let everyone else know about one of the new concepts we&amp;rsquo;re introducing around application structure. As we&amp;rsquo;ve previously discussed, Windows Phone 7 applications are composed of pages that exist on a back stack and can be accessed by the user with the hardware Back key.&lt;/p&gt;
&lt;p&gt;What we haven&amp;rsquo;t been so clear on is exactly which parts of an application &lt;i&gt;should&lt;/i&gt; be a page and which parts &lt;i&gt;shouldn&amp;rsquo;t&lt;/i&gt; be a page, and lots of folks both internally and externally have been bumping into issues around &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/08/01/exiting-a-windows-phone-application.aspx"&gt;login screens&lt;/a&gt;, infinitely-growing back stacks, and so on. The good news is that we finally have some guidance to share around these issues that should help you to build apps that fit in with the navigation-based user model and still meet all your functional requirements. Not to worry though &amp;ndash; this isn&amp;rsquo;t something entirely new. It&amp;rsquo;s just a refinement on the page-based model we&amp;rsquo;ve been talking about all along, but takes into account transient UI, content browsing, and other scenarios. We&amp;rsquo;ve also tweaked the 1&lt;sup&gt;st&lt;/sup&gt;-party apps to follow this model, whereas in the past there were some inconsistencies there, too.&lt;/p&gt;
&lt;p&gt;The basic premise is that the phone (and hence the applications on it) consist of a set of &amp;ldquo;places.&amp;rdquo; A place is a &amp;ldquo;user-recognizable collection of persistent state&amp;rdquo; (thanks to Alan Bush for that succinct description!) or in layman&amp;rsquo;s terms it&amp;rsquo;s a screen that the user visits that contains information, content, or links to other places. Now since a picture is worth a thousand words, let&amp;rsquo;s take a look at the structure of a typical content-browsing application (click to enlarge):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/7356.places_5F00_1802C878.jpg"&gt;&lt;img height="270" width="492" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/8666.places_5F00_thumb_5F00_2574ED4C.jpg" alt="places" border="0" title="places" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(I apologise for the muted tone of that image; the Tech-Ed organisers like to use a very bland palette in the slide templates!)&lt;/p&gt;
&lt;p&gt;What the picture is showing is a simple app that consists of a Home Screen, an All Widgets list, a Details View for Widgets (which consists of several pivots), a Details View for Gadgets, a Search screen and a Settings screen. The application also has a Splash Screen and a Login screen. The arrows represent transitions between screens, with the special case for Login that several of the screens can show the login screen depending on various situations (returning from tombstoning, cookies timing out, etc.). Note that both the Widgets details page and the Gadget details page have little circular arrows on them, meaning you can transition from one Widget (or Gadget) to another without going to a new screen &amp;ndash; this is very much like the way Outlook on the desktop lets you switch to the Previous or Next mail inside the same item window by clicking on the little blue arrows:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/6786.outlookmoveicon_5F00_7A00A684.jpg"&gt;&lt;img height="203" width="232" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-30-21-metablogapi/0336.outlookmoveicon_5F00_thumb_5F00_659AE0F9.jpg" alt="outlookmoveicon" border="0" title="outlookmoveicon" style="border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Those lucky folks with Windows Phone 7 prototype devices will recognize this same behaviour in Outlook on the phone, too). This is also how a typical photo viewing application works &amp;ndash; once you have drilled down into the album and then into an individual photo, you typically switch to different photos in-place by swiping left or right (or clicking previous / next arrows on the desktop).&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll notice that I was very careful to use the word &amp;ldquo;transition&amp;rdquo; rather than &amp;ldquo;navigate&amp;rdquo; in the description above, because not all the arrows represent navigations &amp;ndash; &lt;i&gt;only transitions between different places are navigations&lt;/i&gt;. The following transitions don&amp;rsquo;t represent navigations because they do not switch to different places (and because they&amp;rsquo;re not navigations, they&amp;rsquo;re not on the backstack and aren&amp;rsquo;t automatically reversed by the back key):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The transition from the Splash Screen to the Home Page, since the Splash Screen is not a place&lt;/li&gt;
&lt;li&gt;The multiple transitions to the Login screen, since the Login Screen is not a place&lt;/li&gt;
&lt;li&gt;The transition from the Widget Details back to itself, because it re-uses the same place&lt;/li&gt;
&lt;li&gt;The transition from the Gadget Details back to itself, because it re-uses the same place&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So hang on &amp;ndash; how did we determine that the Splash Screen and the Login Screen are not places? Well, let&amp;rsquo;s look at the definition again: a &lt;span style="text-decoration: underline;"&gt;user recognizable&lt;/span&gt; collection of&lt;b&gt; &lt;/b&gt;&lt;span style="text-decoration: underline;"&gt;persistent state&lt;/span&gt;. The splash screen clearly doesn&amp;rsquo;t contain any state &amp;ndash; it&amp;rsquo;s just smoke and mirrors to make the app launch seem faster than it really is &amp;ndash; and the login screen doesn&amp;rsquo;t really contain any state either; it simply asks you for credentials. The &amp;ldquo;user recognizable&amp;rdquo; bit can also help you determine if other parts of your UI should be places or not by asking a couple of simple questions: Would the user explicitly want to visit this screen? Would the user remember they were on this screen, and want to return to it? The splash screen and login screen both fail these tests too; you don&amp;rsquo;t really want to see either of these screens (they just appear at the appropriate time) and once you&amp;rsquo;re in the app you don&amp;rsquo;t particularly remember seeing them or want to return to them. They&amp;rsquo;re speed bumps that get in the way of the actual content that the user really cares about.&lt;/p&gt;
&lt;p&gt;Yet another way to think of it: if you were building a web site and could provide a deep link to a particular screen, would you bother to do so? Again the splash screen and the login screen both fail that test, except of course for those sites that want to force you through an intro movie. (I just wasted about half an hour trying to find the old &amp;ldquo;skip intro&amp;rdquo; website &amp;ndash; you know, the one that had an endless intro movie that made fun of Flash intros &amp;ndash; but couldn&amp;rsquo;t find it&amp;hellip; bonus points to anyone who can link to it in the comments!)&lt;/p&gt;
&lt;p&gt;So what to do about these non-place screens and these non-navigational transitions? Well, the splash screen is an easy case because we take care of it for you. It&amp;rsquo;s never on the backstack so the user can never return to it. As for things like the login screen or other transient UI, the Silverlight Popup control is a great solution for showing content that (partially) covers the screen without doing a full navigation. And of course you can hook up the &lt;b&gt;BackKeyPress&lt;/b&gt; event and set &lt;b&gt;e.Cancel&lt;/b&gt; to &lt;b&gt;true&lt;/b&gt; while the login screen / popup dialog / etc. is visible to enable the familiar &amp;ldquo;back closes dialogs&amp;rdquo; behaviour without worrying about navigation.&lt;/p&gt;
&lt;p&gt;For places that are used to view multiple pieces of content (Widgets and Gadgets in this case), you can transition between them easily enough without navigating by simply re-binding the controls on your page to a new &lt;b&gt;DataContext&lt;/b&gt;, or by loading multiple instances of a &lt;b&gt;UserControl &lt;/b&gt;inside of the page, or by any other mechanism that you might like to use for showing new content inside a single page. The mechanism through which the user transitions forwards and backwards through the items is up to you &amp;ndash; for example, using &amp;ldquo;previous&amp;rdquo; and &amp;ldquo;next&amp;rdquo; AppBar buttons &amp;ndash; but whatever you do &lt;i&gt;please don&amp;rsquo;t abuse the Back key for local transitions!&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;One question that is left up to the reader is whether to save a local history of transitions that occur in a given place so that if the application is tombstoned the user can retrace their steps. I say &amp;ldquo;local history&amp;rdquo; because these aren&amp;rsquo;t navigations and aren&amp;rsquo;t on the backstack and hence aren&amp;rsquo;t managed by the normal backstack (and I repeat: whatever you do, &lt;span style="text-decoration: underline;"&gt;don&amp;rsquo;t override the Back key to unwind the local history of a given place!&lt;/span&gt;). For some things, like simple previous / next browsing (e-mails, photos, search results, etc.) all you need to save in your page &lt;b&gt;State&lt;/b&gt; is the current index, which along with your &lt;b&gt;NavigationContext&lt;/b&gt; should provide all the information you need to traverse the dataset when returning from a tombstoned state. For applications that have a more complex local transition history, such as free-form browsing of linked items (think: Amazon- or IMDB- style application), you may choose to store some of that history in page state but you will probably want to put a reasonable limit on the number of items you store. The key point is that if the user hits the hardware Back key they return to the previous place (eg, category screen, search results list, etc.) and &lt;span style="text-decoration: underline;"&gt;not&lt;/span&gt; to the previously-viewed item.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a handy guide you can use to help figure out what common parts of an application are places and which are not:&lt;/p&gt;
&lt;table cellpadding="5" cellspacing="0" border="1" style="width: 632px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="197" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Type of screen&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="143" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Place?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="290" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Notes&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="201" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Splash screen&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="147" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;No&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="286" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Transient part of the startup experience; user cannot navigate to it&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="202" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Panorama&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="149" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Yes&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="285" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;A common &amp;ldquo;home screen&amp;rdquo; approach for Windows Phone applications&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="203" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Details page&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="150" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Yes&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="284" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Very common for data-centric apps, parameterised via the query string&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="203" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Pivot item&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="151" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;No&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="283" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;A pivot item is a smaller part of the larger pivot page, which is the place of interest&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="203" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Login dialog or Error dialog&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="152" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;No&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="283" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Transient UI triggered by application state; user does not navigate to it directly&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="202" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Item enumeration&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="152" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;No&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="283" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Browsing similar content is an &amp;ldquo;in-place&amp;rdquo; activity, not a navigation&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;And a quick summary of how to deal with various types of screens:&lt;/p&gt;
&lt;table cellpadding="5" cellspacing="0" border="1" style="width: 627px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="104" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Screen type&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="157" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Implementation&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="220" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Back key behaviour&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="144" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Tombstone behaviour&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="111" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Place&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="163" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;PhoneApplicationPage&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="214" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Automatically goes back or exits the application&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Don&amp;rsquo;t override except in the case of data loss&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="142" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Automatically remains on backstack&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="115" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Transient UI&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="166" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Popup, ChildWindow, etc.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="212" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Application should override to cancel the popup&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;SIP and MessageBox automatically cancel themselves on back&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="141" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Application should dismiss / cancel popup during navigation&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="117" valign="top"&gt;
&lt;p&gt;&lt;b&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Item Enumeration&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="168" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;UserControl etc.&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="210" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;N/A; hosted inside of parent page&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width="145" valign="top"&gt;
&lt;p&gt;&lt;span style="FONT-FAMILY: ; FONT-SIZE: x-small"&gt;Application should save active item as appropriate&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10055327" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/TechEd/">TechEd</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Crazy Coincidental Coding, Batman!</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/17/crazy-coincidental-coding-batman.aspx</link><pubDate>Tue, 17 Aug 2010 23:17:54 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10051214</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10051214</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10051214</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/17/crazy-coincidental-coding-batman.aspx#comments</comments><description>&lt;p&gt;My Silverlight cohort and all-round good guy Shawn Oster posted on &lt;em&gt;exactly &lt;/em&gt;the same topic that I did at almost exactly the same time... and we didn't co-ordinate it at all!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx"&gt;http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Creepy, huh?&lt;/p&gt;
&lt;p&gt;Shawn goes into more detail and calls out one of the key requirements for virtualization, which is that you must have a custom DataTemplate in order for virtualization to kick in.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10051214" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Randomness/">Randomness</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Virtualizing Data in Windows Phone 7 Silverlight Applications</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx</link><pubDate>Tue, 17 Aug 2010 06:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10050871</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10050871</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10050871</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx#comments</comments><description>&lt;p&gt;One of the cool features of lists in Silverlight is that they can "virtualize" the UI objects needed to render the list, reducing the amount of memory and CPU necessary to load large lists. For example, if you bind a &lt;strong&gt;ListBox&lt;/strong&gt; to 1,000 items in Silverlight, it will only create &lt;strong&gt;ListBoxItems&lt;/strong&gt; for the first few screens' worth of data (say, 30 objects) and create the UI for those based on the &lt;strong&gt;DataTemplate&lt;/strong&gt;. The other 970 items do not get UI objects generated for them, which is a great saving of resources. As you scroll through the list, Silverlight recycles these container items and binds them against the rest of the data, giving the illusion that all the items are in the list at once.&lt;/p&gt;
&lt;p&gt;One of the limitations of this in desktop Silverlight is that although the UI is virtualized, the data is not -- so although that 1,000 item list only has a fraction of the UI elements created, it needs all 1,000 of the data objects created and loaded, which can be a resource issue (long load times / high memory usage). This is because in desktop Silverlight the &lt;strong&gt;ListBox &lt;/strong&gt;and other controls databind to &lt;strong&gt;IEnumerables&lt;/strong&gt;, where the only option the control has is to enumerate the entire list to find out how large it is.&lt;/p&gt;
&lt;p&gt;Enter Silverlight for Windows Phone, where we are more resource constrained than the desktop and can't afford to create all those data items like the desktop can. A simple solution is available for this, called data virtualization. The trigger for this is using an object that implementes &lt;strong&gt;IList &lt;/strong&gt;(instead of just &lt;strong&gt;IEnumerable&lt;/strong&gt;) as your &lt;strong&gt;ItemsSource&lt;/strong&gt;. Using this more flexible interface, Silverlight can simply query the list's &lt;strong&gt;Count &lt;/strong&gt;to find out how large it is and can request the individual items it needs to fill the virtualized UI objects via the indexer. This approach enables databounds lists in Windows Phone 7 to be essentially unlimited in size; the sample attached to this post is a list of 1,000,000 objects (yes, &lt;em&gt;&amp;lt;Dr. Evil voice&amp;gt;&lt;/em&gt;&lt;strong&gt;one million objects!&lt;/strong&gt;&lt;em&gt;&amp;lt;/Dr. Evil voice&amp;gt;&lt;/em&gt;) that &lt;em&gt;binds &lt;/em&gt;incredibly quickly, &lt;em&gt;jumps to any point &lt;/em&gt;incredibly quickly, and &lt;em&gt;scrolls like a champ&lt;/em&gt;. Try doing that on the desktop!&lt;/p&gt;
&lt;p&gt;The sample also shows using a (very, &lt;em&gt;very &lt;/em&gt;dumb) cache for storing even more objects than Silverlight virtualizes, in case you want to speed up certain operations. In this example, the cache is a dumb MRU cache that really only works for scrolling back through the list (if you scroll from 0 - 50 and then scroll back down to 0, a lot of the items will be returned as "cached items"). I don't recommend you actually use this cache, because it is dumb and slow, but you can see how the technique could be used to provide smart caching, or even predictive pre-loading of items, etc. to best balance memory usage and performance.&lt;/p&gt;
&lt;p&gt;The only IList members you need to implement are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Count&lt;/strong&gt;, to return the actual number of items in your list;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IndexOf&lt;/strong&gt;, to return the index of a specified item if it is in the list; and&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;this[]&lt;/strong&gt;, to return the item at a given location (implementing &lt;strong&gt;set&lt;/strong&gt; is not required)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything else can simply throw &lt;strong&gt;NotImplementedException&lt;/strong&gt;, although of course it is nice to implement the other members if you play to use your data list in any context other than databinding.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10050871" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-05-08-71/VirtualizingDataTest.zip" length="22214" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Homeward Bound...</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/16/homeward-bound.aspx</link><pubDate>Tue, 17 Aug 2010 05:14:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10050849</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10050849</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10050849</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/16/homeward-bound.aspx#comments</comments><description>&lt;p&gt;Well, well, well. There I was sitting in my office when I get an e-mail asking if I wanted to present Windows Phone 7 developer content at &lt;a href="http://australia.msteched.com/" target="_blank"&gt;Tech.Ed Australia&lt;/a&gt; and &lt;a href="http://newzealand.msteched.com/" target="_blank"&gt;Tech.Ed New Zealand&lt;/a&gt;... what did they think I'd say - &amp;quot;No&amp;quot;?!? :-)&lt;/p&gt;  &lt;p&gt;Suffice it to say I'll be at both conferences, and spending some time in Sydney and Melbourne as well so if you're going to be at the conference maybe I'll see you there. I will be presenting the same kind of content that was already given at Mix 10 and Tech.Ed US, but it will be updated with the latest information on navigation, controls, and so on.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10050849" width="1" height="1"&gt;</description></item><item><title>Updated Tilt Effect</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/11/updated-tilt-effect.aspx</link><pubDate>Wed, 11 Aug 2010 08:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10048767</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10048767</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10048767</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/11/updated-tilt-effect.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://www.jeff.wilcox.name/2010/08/tiltcontentcontrol/"&gt;Jeff has posted&lt;/a&gt; a version of the Windows Phone 7 &amp;ldquo;tilt&amp;rdquo; effect that is packaged as a control, built by Luke. It&amp;rsquo;s only fair that I update my tilt code too &amp;ndash; it uses the same attached property implementation as &lt;a href="http://blogs.msdn.com/b/ptorr/archive/2010/03/23/tilt-effect-for-windows-phone-controls.aspx"&gt;my previous tilt code&lt;/a&gt;, but the new updated tilt algorithm (direct from the shell team) that is used in Luke&amp;rsquo;s control. &lt;/p&gt;
&lt;p&gt;This version uses a global camera effect to ensure that each object tilts not only around its own centre, but is also angled towards the middle of the screen. This effect is accomplished by first translating the object to the middle of the screen doing a normal &lt;strong&gt;RenderTransform&lt;/strong&gt; (in 2D space), and then transforming it back where it came from using a &lt;strong&gt;Projection &lt;/strong&gt;(in 3D space):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;&lt;span style="color: #4bacc6;"&gt;TranslateTransform&lt;/span&gt;&lt;/strong&gt; transform = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;strong&gt;&lt;span style="color: #4bacc6;"&gt;TranslateTransform&lt;/span&gt;&lt;/strong&gt;(); &lt;br /&gt;transform.X = centerDelta.X; &lt;br /&gt;transform.Y = centerDelta.Y; &lt;br /&gt;element.RenderTransform = transform;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New;"&gt;&lt;strong&gt;&lt;span style="color: #4bacc6;"&gt;PlaneProjection&lt;/span&gt;&lt;/strong&gt; projection = &lt;span style="color: #0000ff;"&gt;new&lt;/span&gt; &lt;strong&gt;&lt;span style="color: #4bacc6;"&gt;PlaneProjection&lt;/span&gt;&lt;/strong&gt;(); &lt;br /&gt;projection.GlobalOffsetX = -1 * centerDelta.X; &lt;br /&gt;projection.GlobalOffsetY = -1 * centerDelta.Y; &lt;br /&gt;element.Projection = projection;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a relatively simple trick that is used in several other places in the Windows Phone 7 animations, something I hope to be posting more on later.&lt;/p&gt;
&lt;p&gt;Other than the global camera, a switch to using manipulation events, and some general code clean-up, the basic technique has not changed from the previous version:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An attached property, &lt;strong&gt;TiltEffect.IsTiltEnabled&lt;/strong&gt;, can be placed on any element in the tree (typically the root of a page or even the frame)&lt;/li&gt;
&lt;li&gt;When this is done, the control starts listening for &lt;strong&gt;ManipulationStarted&lt;/strong&gt; events on that element&lt;/li&gt;
&lt;li&gt;If a manipulation is detected, the code checks the object being manipulated to check whether it is a "tiltable" object&lt;/li&gt;
&lt;li&gt;If it is, the appropriate &lt;strong&gt;RenderTransform&lt;/strong&gt; and &lt;strong&gt;Projection&lt;/strong&gt; are added to the element, and the &lt;strong&gt;ManipulationDelta&lt;/strong&gt; and &lt;strong&gt;ManipulationCompleted&lt;/strong&gt; events are hooked&lt;/li&gt;
&lt;li&gt;Whenever your finger (mouse) moves, the tilt angle is updated&lt;/li&gt;
&lt;li&gt;When the manipulation completes (or when you leave the hit-area of the control) an animation is run to "spring" the control back into place after a short delay&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is all done in a pretty efficient way, such that there is only ever one animation in the app and so that the added transforms and projections are removed after use. Attached is a simple example project that uses the updated effect along with some super-ugly demo pages that show the effect in, errr, effect. It also behaves nicely with tombstoning so that it remembers the scroll positions of each page and the settings you have chosen on the first page. Fingers crossed, this will also make it into the official documentation as a sample such that even developers who &lt;em&gt;don't&lt;/em&gt; read my blog will have access to the tilt effect in their apps (although shame on them for not reading! ;-) ).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10048767" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-04-87-67/TiltEffectRtm.zip" length="27248" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item><item><title>Jeff’s improved ProgressBar template</title><link>http://blogs.msdn.com/b/ptorr/archive/2010/08/02/jeff-s-improved-progressbar-template.aspx</link><pubDate>Mon, 02 Aug 2010 20:57:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10045124</guid><dc:creator>Peter Torr - MSFT</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/rsscomments.aspx?WeblogPostID=10045124</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/ptorr/commentapi.aspx?WeblogPostID=10045124</wfw:comment><comments>http://blogs.msdn.com/b/ptorr/archive/2010/08/02/jeff-s-improved-progressbar-template.aspx#comments</comments><description>&lt;p&gt;Another quick post... Jeff Wilcox has posted an improved template for the Indeterminate &lt;strong&gt;ProgressBar&lt;/strong&gt; for Windows Phone. He goes into a little of the history behind this, too. I recommend you use his updated control if you are showing an indeterminate progress bar and seeing sluggish performance.&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.jeff.wilcox.name/2010/08/performanceprogressbar/" href="http://www.jeff.wilcox.name/2010/08/performanceprogressbar/"&gt;http://www.jeff.wilcox.name/2010/08/performanceprogressbar/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10045124" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/WP7S/">WP7S</category><category domain="http://blogs.msdn.com/b/ptorr/archive/tags/Silverlight/">Silverlight</category></item></channel></rss>
