With successful Windows Phone 7 apps on the Marketplace, including award-winning AppTracker, the VerySoftware team is keen to share their experience and passion about creating apps for Windows Phone 7.
By combining the powers of developer and designer they will run through the creation of a sample app, demoing tips and tricks to take your app's user experience to the next level.
This presentation was prepared for Microsoft UK Tech.Days held in London on May 24th 2011.
Presentation resources:
---------------------------
Tech.Days sample app source code
http://verysoftware.co.uk/talks/techdays/
AppTracker app
http://verysoftware.co.uk/apptracker
Polyglot app
http://verysoftware.co.uk/polyglot
3. menu entrée designing for windows phone 7: our experience main apptracker:the ultimate app for developers dessert building tech.days app: tips & tricks
24. apptracker: 300+ reviews thank you for your support! “ “ “ “ “ “ “ “ “ truly brilliant app coolest app for developers! perfect for developers! an essential app! simply awesome extremely useful app for developers excellent design a must have for every WP7 developer ” love it! ” ” ” ” ” ” ” ”
25. apptracker: our favourite comment “ superb app. why only four stars? because it should be $5. you're letting the rest of us devs down by giving away such great free stuff! ”
52. tips & tricks: different levels of details optimise for mobile
53. tips & tricks: different levels of details optimise for mobile
54. tips & tricks: transitions “ the experience is in the transition between states, not the states themselves. bill buxton, principal researcher microsoft research, mix’09 video ”
81. useful resources: our apps polyglot– your personal translator: 30+ languages, pronunciation, translation history. free trial: http://bit.ly/dJYItw apptracker– the ultimate tool to keep track of your windows phone 7 apps on the marketplace. free for a limited time: http://bit.ly/hRlfik gifts– a simple and elegant gifts organiser: don’t make the mistake of missing a gift this year. free version: http://bit.ly/i2cHRH
85. rapid development: polyglot app made in 10 hoursapptracker: the best way to track your apps tips & tricks building tech.days app: it’s the little details and extra touches that really make an app delicious!
86. many thanks! we create delicious software windows phone, silverlight, wpf, iphone, ipad @verysoftware verysoftware.co.uk contact@verysoftware.co.uk
Hinweis der Redaktion
Code:private static bool? cachedIsTrialMode = null;public static bool IsTrialMode(){ return IsTrialMode(false);} public static bool IsTrialMode(bool forceFromCache) { // If this code is being run buy VS/Blend design tool, we don't want to MessageBox if (DesignerProperties.IsInDesignTool) return false; if ((forceFromCache) || (cachedIsTrialMode == null)) {#if DEBUGMessageBoxResult result = MessageBox.Show("Click ok to simulate paid version", "Simulate paid version?", MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) {cachedIsTrialMode = false; } else {cachedIsTrialMode = true; }#elseLicenseInformationlicenseInfo = new LicenseInformation();cachedIsTrialMode = licenseInfo.IsTrial();#endif } return cachedIsTrialMode.Value; }
Code:using Microsoft.Phone.Tasks;using Tomers.Phone.Controls;private static bool PerformedRatingPromptCheck = false;private void PhoneApplicationPage_Loaded(object sender, System.Windows.RoutedEventArgs e){ if (!PerformedRatingPromptCheck) {PerformedRatingPromptCheck = true;intnumAppLaunches = 0;IsolatedStorageSettings.ApplicationSettings.TryGetValue<int>("Rating_numAppLaunches", out numAppLaunches);intnumNextRatingPrompt = 0; if (!IsolatedStorageSettings.ApplicationSettings.TryGetValue<int>("Rating_numNextRatingPrompt", out numNextRatingPrompt)) {numNextRatingPrompt = 5; } if (numAppLaunches >= numNextRatingPrompt) {IsolatedStorageSettings.ApplicationSettings["Rating_numNextRatingPrompt"] = numNextRatingPrompt * 2;NotificationBox.ShowAgain("Enjoying the app?", "Would you like to rate this app now?", "Ask me later", false,Surpressed => { }, "Rating_MsgPrompt", new NotificationBoxCommand("Yes", () => { new MarketplaceReviewTask().Show(); }), new NotificationBoxCommand("No", () => { })); }IsolatedStorageSettings.ApplicationSettings["Rating_numAppLaunches"] = numAppLaunches + 1; }}
Code:NotificationBox.ShowAgain("Enjoying the app?", "Would you like to rate this app now?", "Ask me later", false,Surpressed => { }, "Rating_MsgPrompt", new NotificationBoxCommand("Yes", () => { new MarketplaceReviewTask().Show(); }), new NotificationBoxCommand("No", () => { }));
Code:// Code to execute on Unhandled Exceptionsprivate void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e){ if (System.Diagnostics.Debugger.IsAttached) { // An unhandled exception has occurred; break into the debuggerSystem.Diagnostics.Debugger.Break(); } else {var result = MessageBox.Show("Would you like to email the details of this error to the Developer?\\n\\n(No personal information, other than your email address, will be sent to the Developer)", "An error has occurred!",MessageBoxButton.OKCancel); if (result == MessageBoxResult.OK) {var task = new EmailComposeTask();task.To = "contact@DeveloperEmailAddress.com";task.Subject = "Error Report: TechDays 2011 App";task.Body = String.Format("An unhandled exception occurred in TechDays 2011 App:\\n\\n{0}", e.ExceptionObject.ToString());task.Show(); } }}
Code:void BackgroundLoadFavouriteSessions(object sender, DoWorkEventArgs e){varfavIDs = LoadFavouriteSessionsFromFile(); if (favIDs == null) { // We failed when loading from file so check the cloud storeCloudUserDataServiceClient client = new CloudUserDataServiceClient();client.GetStoredTechDaysUserDataCompleted += client_GetStoredTechDaysUserDataCompleted;client.GetStoredTechDaysUserDataAsync(HelperFuncs.UserID); } else { // Loaded from file successfully so use this dataSetFavourites(GetSessionListFromIDs(favIDs)); }}void client_GetStoredTechDaysUserDataCompleted(object sender, GetStoredTechDaysUserDataCompletedEventArgs e){ if ((e.Error == null) && (e.Result != null) && (!String.IsNullOrEmpty(e.Result.FavouriteIDs))) { if (MessageBox.Show("Would you like to restore your settings for this app?", "No settings found", MessageBoxButton.OKCancel) == MessageBoxResult.OK) {varfavouriteSessionList = GetSessionListFromIDString(e.Result.FavouriteIDs);SetFavourites(favouriteSessionList); } }}
Code:private static string cachedUserID = null;public static string UserID{ get { if (cachedUserID == null) { string anid = UserExtendedProperties.GetValue("ANID") as string; if (anid != null) {cachedUserID = anid.Substring(2, 32); } else {cachedUserID = "EMULATOR_USER"; } } return cachedUserID; }}private void SaveFavouritesToCloud(string favIDString){TechDaysUserDatasaveData = new TechDaysUserData() {UserID = HelperFuncs.UserID,FavouriteIDs = favIDString };CloudUserDataServiceClient client = new CloudUserDataServiceClient();client.StoreTechDaysUserDataAsync(saveData);}
Code:public class TechDaysDataEntryContext : TableServiceContext{ public static string TableName = "TechDaysDataEntrys"; public TechDaysDataEntryContext(CloudStorageAccount account) : base(account.TableEndpoint.ToString(), account.Credentials) { } public IQueryable<TechDaysDataEntry> TechDaysDataEntrys { get { return this.CreateQuery<TechDaysDataEntry>(TableName); } } public void AddTechDaysDataEntry(TechDaysDataEntrynewEntry) {this.AddObject(TableName, newEntry);this.SaveChanges(); }}public class TechDaysDataEntry : TableServiceEntity{ public string UserID { get { return PartitionKey; } set { RowKey = value; PartitionKey = value; } } public string FavouriteIDs { get; set; } public TechDaysDataEntry() { } public TechDaysDataEntry(string UserID, string inFavouriteIDs) {PartitionKey = UserID;RowKey = UserID;FavouriteIDs = inFavouriteIDs; }}
Code:public TechDaysUserDataGetStoredTechDaysUserData(string userID){varstorageAccount = GetStorageAccount();vartddeContext = new TechDaysDataEntryContext(storageAccount);tddeContext.IgnoreResourceNotFoundException = true;var result = (from entry in tddeContext.TechDaysDataEntrys where entry.PartitionKey == userID && entry.RowKey == userID select entry).ToList(); if (result.Count == 1) {var entry = result.First();varuserData = new TechDaysUserData() {UserID = entry.UserID,FavouriteIDs = entry.FavouriteIDs }; return userData; } return null;}public void StoreTechDaysUserData(TechDaysUserDatauserData){varstorageAccount = GetStorageAccount();vartddeContext = new TechDaysDataEntryContext(storageAccount);tddeContext.IgnoreResourceNotFoundException = true;var result = (from entry in tddeContext.TechDaysDataEntrys where entry.PartitionKey == userData.UserID && entry.RowKey == userData.UserID select entry).ToList(); if (result.Count == 0) {var entry = new TechDaysDataEntry(userData.UserID, userData.FavouriteIDs);tddeContext.AddTechDaysDataEntry(entry); } else {var entry = result.First();entry.FavouriteIDs = userData.FavouriteIDs;tddeContext.UpdateObject(entry);tddeContext.SaveChanges(); }}[DataContract]public class TechDaysUserData{ [DataMember] public string UserID{ get; set; } [DataMember] public string FavouriteIDs { get; set; }}