Hands-OnLab

Launchers

Lab version:1.0.0

Last updated:10/26/2018

CONTENTS

Overview

Exercise 1: Introduction to the Windows Phone Launchers

Task 1 – Using Launchers

Summary

Overview

ThelaunchersandchoosersframeworkenablesWindowsPhoneapplicationstoprovidecommonfunctionssuchasplacingphonecalls,sendingemails,andtakingpicturesfortheirusers.

TheWindowsPhoneapplicationmodelisolateseveryapplicationinitsownworkareaforbothexecution(includingmemoryisolation)andfilestorage.WindowsPhoneapplicationsarenotabletodirectlyaccesscommoninformationstoressuchasthecontactslistortodirectlyinvokeotherapplicationssuchasphoningormessaging.Tosupportscenariosrequiringcommontaskssuchasphoningormessaging,theWindowsPhoneprovidesasetoflauncherandchooserAPIsthatenablesapplicationstoaccesstheseusefulphonefeaturesindirectly.ThelauncherandchooserAPIsinvokedistinctbuilt-inapplicationsthatreplacethecurrentlyrunningapplication.Thelaunchersandchoosersframeworkprovidestheenduserwithaseamlessexperiencewhilemaskingtheapplicationswitchingthatoccursinthebackground.

Theframeworkcomponentsareasfollows:

  • Launcher-A“fireandforget”action,whereaspecificWindowsPhonefunctionalityislaunched,forexample,sendinganSMSmessage,openingawebpage,orplacingaphonecall

BelowisthecompletelistoflaunchersthatWindowsPhone7Codenamed “Mango” supports:

Launchers

  • ConnectionSettingsTask - Enables to launch system settings application to control various connection settings
  • EmailComposeTask-Enablesanapplicationtolaunchtheemailapplicationwithanewmessagealreadydisplayed,souserscansendemailmessagesfromwithinanapplication
  • MarketplaceDetailTask-EnablesanapplicationtolaunchtheWindowsPhoneMarketplaceclientapplicationanddisplaythedetailspageforthespecifiedproduct
  • MarketplaceHubTask-EnablesanapplicationtolaunchtheWindowsPhoneMarketplaceclientapplication
  • MarketplaceReviewTask-EnablesanapplicationtolaunchtheWindowsPhoneMarketplaceclientapplicationanddisplaythereviewpageforthespecifiedproduct
  • MarketplaceSearchTask-EnablesanapplicationtolaunchtheWindowsPhoneMarketplaceclientapplicationanddisplaythesearchresultsfromthespecifiedsearchparameters
  • MediaPlayerLauncher-Enablesanapplicationtolaunchthemediaplayer
  • PhoneCallTask-EnablesanapplicationtolaunchthePhoneapplication,souserscanmakeaphonecallfromwithinanapplication
  • SaveContactTask - Enables an application to launch the contacts application and provide initial data for new contact, so users can save the data from within an application to a new contact
  • SaveEmailAddressTask-Enablesanapplicationtolaunchthecontactsapplication,souserscansaveanemailaddressfromwithinanapplicationtoaneworexistingcontact
  • SavePhoneNumberTask-Enablesanapplicationtolaunchthecontactsapplicationsouserscansaveaphonenumberfromwithinanapplicationtoaneworexistingcontact
  • SearchTask-EnablesanapplicationtolaunchtheWebSearchapplication
  • ShareLinkTask - Enables an application to post a link with title and message via user’s social network account
  • ShareStatusTask - Enables an application to post status update via user’s social network account
  • SmsComposeTask–EnablesanapplicationtolaunchtheSMSapplication
  • WebBrowserTask-EnablesanapplicationtolaunchtheWebBrowserapplication

WhileitisalwaysagoodpracticetothinkaboutapplicationtombstoningduringWindowPhonedevelopment,oneshouldconsidertombstoningevenmoreseriouslywhendealingwithlaunchersandchoosers.

Whendoesanapplicationgettombstoned?

Generallyspeaking,anapplicationgetstombstoned[thatis,itisplacedinthebackstack]whenauserforwardnavigatesawayfromit.Whilethereareafewexceptionstothisgeneralrule,applicationsinthebackgroundmaybetombstonedatanytimeifthesystemrequiresadditionalresourcestocarryoutthecurrentforegroundactivity.

Anapplicationwillnotbeautomaticallytombstonedwhenitlaunchesanexperiencethatfeelstotheuserlikeanextensionoftheoriginalapplication.Theseexperiencesarenativeflowsthathelptheusercompletesometask,likechoosingaphoto.Avoidingtombstoninginthesecasesensuresasmoothflowbetweentheapplicationandtheexperienceithascalled[forexample,nodelaybetweenchoosingaphotoandreturningtotheapplicationthatusesit].

Belowisthelistofnativeexperiencesthat,wheninvoked,donottriggeranautomatictombstoneinthecallingapplication:

  • PhotoChooserTask
  • CameraCaptureTask
  • MediaPlayerLauncher
  • EmailAddressChooserTask
  • PhoneNumberChooserTask

Therearethreescenariosinwhich anapplicationinthebackgroundwillimmediatelybetombstoned:

  • Userforwardnavigatesawayfromanapplication[forexample,userpressestheStartkey]
  • Applicationinvokeslaunchersorchoosersnotlistedabove
  • Systemrequiresmoreresourcestocarryoutaforegroundactivity

Note:AlltheaboveinformationregardingtombstoningistrueforWindows®Phone7.0.OnWindows®Phone7.1launchersandchoosersneverinitiatetombstoning,butitmaybeinitiatednonethelessifthedevicerequiresadditionalresources.Formoreinformationonthenew7.1applicationexecutionmodelplease refer to documentation.

Objectives

Uponcompletionofthislab,youwill:

  • BefamiliarwiththelaunchersandchoosersconceptasimplementedintheWindowsPhone7applicationmodel
  • Understandhowandwhentouselaunchersandchoosers
  • HavecreatedaSilverlightapplicationthatusesthewidearrayofavailablelaunchersandchoosers

Prerequisites

Thefollowingisrequiredtocompletethishands-onlab:

  • MicrosoftVisualStudio2010ExpressforWindowsPhoneorMicrosoftVisualStudio2010
  • WindowsPhoneCodenamed “Mango”DeveloperTools

Note:Youcandownloadallofthesetoolstogetherinasinglepackagefrom

Exercises

Thishands-onlabiscomprisedofthefollowingexercises:

  • IntroductiontotheWindowsPhoneLaunchers

Estimatedtimetocompletethislab:30minutes.

Exercise 1: Introduction to the Windows Phone Launchers

Inthisexercise,youopenthestartersolutionandcompletethefollowingtasks:

  • Addandnavigatetomultiplepages
  • Exploreadifferentlauncheroneachpage

The starting point for this exercise is the solution located in the lab installation folder under the Source\Begin folder.

Task1–UsingLaunchers

AlauncherisanAPIthatlaunchesoneofthebuilt-inapplicationsthroughwhichausercompletesataskandinwhichnodataisreturnedtothecallingapplication.AnexampleofthisisthePhoneCallTask.Anapplicationcanprovidethislauncherwithaphonenumberandadisplaynamewithwhichtoinvokethephone.Whenthephoneapplicationisdisplayed,theusercanselectwhethertoinitiateacallusingthesuppliedparameters.Whentheuserclosesthephoneapplication,thecallingapplicationisusuallyactivatedagain,butthephoneapplicationdoesnotreturnanydataaboutorresultingfromtheuser’sactions.Whenanapplicationinvokesalauncher,itdoesnotgetareturnvalue.

  1. OpenSavePhoneNumberPage.xaml.cs.
  2. AddthefollowingcodetotheSavePhoneNumberPageclass:

C#

//Regexpatternsprovidedby

conststringphoneNumberPattern=@"^([0-9](|-)?)?(\(?[0-9]{3}\)?|[0-9]{3})(|-)?([0-9]{3}(|-)?[0-9]{4}|[a-zA-Z0-9]{7})$";

  1. Addthefollowingusingstatements:

C#

usingSystem.Text.RegularExpressions;

usingMicrosoft.Phone.Tasks;

usingSystem.Diagnostics;

usingSystem.Windows.Navigation;

  1. OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethephonenumberintothepage'sstatesoitcanbedisplayedagainincasetheapplicationistombstoned.

C#

protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedFromfunctionofSavePhoneNumberPage\t***");

if(State.ContainsKey(inputStateKey))

State.Remove(inputStateKey);

State.Add(inputStateKey,txtInput.Text);

base.OnNavigatedFrom(e);

}

protectedoverridevoidOnNavigatedTo(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedTofunctionofSavePhoneNumberPage\t***");

if(State.ContainsKey(inputStateKey))

{

stringinput=(string)State[inputStateKey];

txtInput.Text=input;

State.Remove(inputStateKey);

}

base.OnNavigatedTo(e);

}

  1. AddtheinputstatekeyconstanttotheSavePhoneNumberPageclass.

C#

conststringinputStateKey="input";

  1. AddaSavePhoneNumberTaskvariabletotheSavePhoneNumberPageclass.

C#

SavePhoneNumberTasksavePhoneNumberTask;

  1. AddthefollowinghighlightedcodetoinitializethesavePhoneNumberTaskvariableintheclassconstructorandoutputdebuginformation.

C#

publicSavePhoneNumberPage()

{

InitializeComponent();

Debug.WriteLine("***\tInconstructorofSavePhoneNumberPage\t***");

savePhoneNumberTask=newSavePhoneNumberTask();

savePhoneNumberTask.Completed+=newEventHandlerTaskEventArgs>(savePhoneNumberTask_Completed);

}

  1. Addthehandlerfunctionforthecompletionevent.

C#

voidsavePhoneNumberTask_Completed(objectsender,TaskEventArgse)

{

Debug.WriteLine("***\tInsavePhoneNumberTask_CompletedfunctionofSavePhoneNumberPage\t***");

if(e.TaskResult==TaskResult.OK)

MessageBox.Show("Phonenumbersavedsuccessfully","Success",MessageBoxButton.OK);

elseif(e.TaskResult==TaskResult.Cancel)

MessageBox.Show("Phonenumberwasnotsaved-operationwascancelled","Contactnotselected",MessageBoxButton.OK);

else

MessageBox.Show("Errorwhilesavingphonenumber:\n"+e.Error.Message,"Fail",MessageBoxButton.OK);

}

  1. Usetheregularexpressiontovalidateuserinput.Ifinputpassesvalidation,usetheSavePhoneNumberTasktosavethevalidatedphonenumber.SavePhoneNumberTaskenablesanapplicationtolaunchthecontactsapplication.Usethistoallowuserstosaveaphonenumberfromthecallingapplicationtoaneworexistingcontact.

C#

privatevoidbtnSavePhone_Click(objectsender,RoutedEventArgse)

{

if(Regex.IsMatch(txtInput.Text,phoneNumberPattern,RegexOptions.IgnoreCase))

{

if(null!=savePhoneNumberTask)

{

savePhoneNumberTask.PhoneNumber=txtInput.Text;

savePhoneNumberTask.Show();

}

}

else

{

MessageBox.Show("Specifiedvalueisnotavalidphonenumber\nValidphonenumberlookslikethefollowing:\n1-(123)-123-1234,1231231234,1-800-ALPHNUM","InvalidInput",MessageBoxButton.OK);

}

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheSavePhoneNumberpageandtypeavalidphonenumber.
  3. ToexecutetheLauncherclickSavePhoneNumber.
  4. AddthephonenumbertoaneworexistingcontactusingthestandardWindows®Phone7interface:

Figure1

Addingaphonenumbertoexistingornewcontact

  1. Optionally,givethecontactaname.
  2. SavethecontactandclickBack():

Figure2

Launcherreturnnotification

Note:TheinsertedphonenumbershouldappearintheinputtextboxeventhoughtheapplicationwassenttothebackgroundduringthePhoneSaveTaskoperation.Analyzethedebugoutputtogainabetterunderstandingofthisprocess.

  1. Repeatthissteptoaddanewcontact.

Note:Theemulatorpreservescontactsdataonlywhenitisrunning.Pleasedonotclosetheemulatorbetweenthesteps.Thisenablesviewingthecontact’sinformationlateroninthelab.

  1. PressSHIFT+F5tostopthedebuggerandreturntoeditingmode.
  2. OpenSaveEmailAddressPage.xaml.cs.
  3. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavetheemailaddressintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
  4. AddaSaveEmailAddressTaskvariabletotheSaveEmailAddressPageclass.

C#

SaveEmailAddressTasksaveEmailAddressTask;

  1. AddthefollowinghighlightedcodetoinitializethesaveEmailAddressTaskvariableintheclassconstructor.

C#

publicSaveEmailAddressPage()

{

InitializeComponent();

Debug.WriteLine("***\tInconstructorofSaveEmailAddressPage\t***");

saveEmailAddressTask=newSaveEmailAddressTask();

saveEmailAddressTask.Completed+=newEventHandlerTaskEventArgs>(saveEmailAddressTask_Completed);

}

  1. Replacethehandlerfunctionforthecompletionevent.

C#

voidsaveEmailAddressTask_Completed(objectsender,TaskEventArgse)

{

Debug.WriteLine("***\tInsaveEmailAddressTask_CompletedfunctionofSaveEmailAddressPage\t***");

if(e.TaskResult==TaskResult.OK)

MessageBox.Show("Emailaddresssavedsuccessfully","Success",MessageBoxButton.OK);

elseif(e.TaskResult==TaskResult.Cancel)

MessageBox.Show("Emailaddresswasnotsaved-operationwascancelled","Contactnotselected",MessageBoxButton.OK);

else

MessageBox.Show("Errorwhilesavingemailaddress:\n"+e.Error.Message,"Fail",MessageBoxButton.OK);

}

  1. Usetheregularexpressiontovalidateuserinput.Ifinputpassesvalidation,usetheSaveEmailAddressTasktosavethevalidatedemailaddress.SaveEmailAddressTaskenablesanapplicationtolaunchthecontactsapplication.Usethistoallowuserstosaveanemailaddressfromwithinthecallingapplicationtoaneworexistingcontact.

C#

privatevoidbtnSaveEmail_Click(objectsender,RoutedEventArgse)

{

if(Regex.IsMatch(txtInput.Text,emailAddressPattern,RegexOptions.IgnoreCase))

{

if(null!=saveEmailAddressTask)

{

saveEmailAddressTask.Email=txtInput.Text;

saveEmailAddressTask.Show();

}

}

else

{

MessageBox.Show("Specifiedvalueisnotavalidemailaddress\nValidemailaddresslookslikethefollowing:\,","InvalidInput",MessageBoxButton.OK);

}

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheSaveEmailpageandtypeavalidemailaddress.
  3. ToexecutetheLauncher,clickSaveEmailAddress.
  4. AddtheemailaddresstoaneworexistingcontactusingthestandardWindows®Phone7interface:

Figure3

Addinganemailaddresstoexistingornewcontact

  1. SavethecontactandclickBack():
  2. PressSHIFT+F5tostopthedebuggerandreturntoeditingmode.
  3. OpenSearchTaskPage.xaml.cs.
  4. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned:
  5. ToexecutethesearchfunctionalitythislabusesSearchTask.SearchTaskenablesanapplicationtolaunchtheWebSearchapplication.LocatethebtnSearch_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnSearch_Click(objectsender,RoutedEventArgse)

{

SearchTasksearchTask=newSearchTask();

searchTask.SearchQuery=txtInput.Text;

searchTask.Show();

}

  1. Compileandruntheapplication.
  2. NavigatetotheSearchpageandinputasearchquery:

Figure4

SearchPage

  1. ClickSearchEverywhere.
  2. It is possible, that the first search execution displays a screen asking toallowlocationinformationusage.ClickAllow.
  3. TheemulatorconnectstotheWebandbringsbackthedefinedqueryresults:

Figure5

WebResults

  1. PressSHIFT+F5tostopthedebuggingandreturntoeditingmodeinVisualStudio.
  2. OpenWebSearchPage.xaml.cs.
  3. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
  4. SilverlighthasaWebBrowsercontrolthatcouldbeusedasanyotherSilverlightcontrolintheapplication.InadditionWindowsPhonehasaWebBrowserlauncherenablingInternetExplorertobestarteddirectlyfromtheapplication.Touseit,thislabusesWebBrowserTask.WebBrowserTaskenablesanapplicationtolaunchtheWebbrowserapplication.LocatethebtnGo_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnGo_Click(objectsender,RoutedEventArgse)

{

WebBrowserTaskwebBrowserTask=newWebBrowserTask();

conststringurl="

webBrowserTask.URL=string.Format(url,txtInput.Text);

webBrowserTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheSearchwithBingpageandinputasearchquery.
  3. TheLauncherstartsInternetExplorerandnavigatestoBingwebpage:

Figure6

Windows®Phone7.1IE

  1. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  2. OpenVideoPlayerPage.xaml.cs.
  3. OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.

C#

protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedFromfunctionofVideoPlayerPage\t***");

base.OnNavigatedFrom(e);

}

protectedoverridevoidOnNavigatedTo(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedTofunctionofVideoPlayerPage\t***");

base.OnNavigatedTo(e);

}

  1. FromtheSource\Assetsfolderofthislab,addanexistingvideofiletotheproject’sMediafolder.
  2. AttheAddExistingItemdialogbrowsetotheAssetsfolderofthislab,selectthevideofile,andfromtheAddbuttondropdownlistselectAddAsLink.

Figure7

Selectingthevideofile

  1. MakesurethevideofilewasaddedasaContentresource.Tocheckit,clickontheaddedfileinSolutionExplorerandpressF4toshowthefileproperties.

Figure8

CheckingtheBuildActionoftheaddedvideofile

  1. Addaneventhandlerfunctiontohandlethebuttonclickevent.ThefunctionwillusetheMediaPlayerLauncherwhichallowsanapplicationtolaunchthemediaplayertoplayavideofile.Addthefollowingcodetotheclass:

C#

privatevoidbtnPlayVideo_Click(objectsender,RoutedEventArgse)

{

MediaPlayerLaunchermediaPlayerLauncher=
newMediaPlayerLauncher();

mediaPlayerLauncher.Location=
MediaLocationType.Install;//meansisaresourceoftheapp,otherwiseitwilltrytoresolveitinData(IsolatedStorage)forapplication

mediaPlayerLauncher.Media=newUri("Media/Bear.wmv",UriKind.Relative);

mediaPlayerLauncher.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheVideoPlayerpageandplaythevideo.
  3. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  4. OpenSaveRingtonePage.xaml.cs.
  5. Addthefollowingusingstatementstotheclass:

C#

usingSystem.IO.IsolatedStorage;

usingSystem.IO;

  1. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosupplydebuginformationwhentheapplication istombstoned.
  2. Addasoundfilethatwillserveasaringtonetotheproject.Performsteps48-50inclusiveasecondtime,butinsteadofadding“Bear.wmv”add“Ring.mp3”.
  3. Addthefollowinghighlightedcodetocreatethedebuginformationintheclassconstructor,andtodeploythesoundfilethatwewilluseasthenewringtonetoisolatedstorage.

C#

publicSaveRingtonePage()

{

InitializeComponent();

Debug.WriteLine("***\tInconstructorofSaveRingtonePage\t***");

PlaceAssetInIsolatedStorage();

}

  1. Addthefollowingadditionalmethodsforstoringtheringtoneinisolatedstorage:

C#

privatestaticvoidPlaceAssetInIsolatedStorage()

{

using(IsolatedStorageFileiso=
IsolatedStorageFile.GetUserStoreForApplication())

{

Streamstr=Application.GetResourceStream(new
Uri("Media/Ring.mp3",UriKind.Relative)).Stream;

IsolatedStorageFileStreamoutFile=iso.CreateFile("Ring.mp3");

outFile.Write(ReadToEnd(str),0,(int)str.Length);

str.Close();

outFile.Close();

}

}

privatestaticbyte[]ReadToEnd(System.IO.Streamstream)

{

longoriginalPosition=stream.Position;

stream.Position=0;

try

{

byte[]readBuffer=newbyte[4096];

inttotalBytesRead=0;

intbytesRead;

while((bytesRead=stream.Read(readBuffer,totalBytesRead,
readBuffer.Length-totalBytesRead))0)

{

totalBytesRead+=bytesRead;

if(totalBytesRead==readBuffer.Length)

{

intnextByte=stream.ReadByte();

if(nextByte!=-1)

{

byte[]temp=newbyte[readBuffer.Length*2];

Buffer.BlockCopy(readBuffer,0,temp,0,
readBuffer.Length);

Buffer.SetByte(temp,totalBytesRead,
(byte)nextByte);

readBuffer=temp;totalBytesRead++;

}

}

}

byte[]buffer=readBuffer;

if(readBuffer.Length!=totalBytesRead)

{

buffer=newbyte[totalBytesRead];

Buffer.BlockCopy(readBuffer,0,buffer,0,totalBytesRead);

}

returnbuffer;

}

finally

{

stream.Position=originalPosition;

}

}

  1. Toallowtheusertoassociatearingtonewithacontact,wewillusetheSaveRingtoneTask.LocatethebtnSaveRingtone_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnSaveRingtone_Click(objectsender,RoutedEventArgse)

{

SaveRingtoneTaskringtoneTask=newSaveRingtoneTask();

ringtoneTask.Source=newUri("isostore:/Ring.mp3",UriKind.Absolute);

ringtoneTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. Navigatetothe“SaveRingtone”pageandpressthescreensonlybutton: “Save Ringtone”
  3. Itwilltakeyoutothephone’sbuilt-inringtonesavingscreen,allowingyoutospecifyafilenameforthesavedringtoneandtosetitastheactiveringtone:

Figure9

Thebuilt-inringtonesavingscreen

  1. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  2. Open SaveContactPage.xaml.cs.
  3. Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
  4. To allow the user to save information from application’s page into phone contacts, we will use the SaveContactTask. Locate the btnSaveContact_Click event handler function and add the following code to the function body (continue the “if” statement provided by starter solution):

C#

else

{

SaveContactTasksaveContactTask=newSaveContactTask();

saveContactTask.Company=txtCompany.Text;

saveContactTask.FirstName=txtFirstName.Text;

saveContactTask.LastName=txtLastName.Text;

saveContactTask.JobTitle=txtJobTitle.Text;

saveContactTask.WorkEmail=txtWorkEmail.Text;

saveContactTask.Website=txtWebsite.Text;

saveContactTask.Nickname=txtNickname.Text;

saveContactTask.Completed+=(s,args)=>

{

if(null==args.Error)

{

MessageBox.Show(string.Format("Contact{0}saved!",
(args.TaskResult==TaskResult.Cancel?"not":"")));

}

else

MessageBox.Show("Errorsavingcontact!");

};

saveContactTask.Show();

}

  1. Press F5 to compile and run the application.

Figure 10

Saving contact information

  1. Navigate to the Save New Contact page, provide required information and click “Save New Contact” button. Save the new contact and click Back ().
  2. Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
  3. OpenComposeEmailPage.xaml.cs.
  4. Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:

C#

publicclassEmailInputData

{

publicstringTo{get;set;}

publicstringCc{get;set;}

publicstringBcc{get;set;}

publicstringSubject{get;set;}

publicstringBody{get;set;}

}

  1. OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavetheemaildataintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.

C#

protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedFromfunctionofComposeEmailPage\t***");

if(State.ContainsKey(inputStateKey))

State.Remove(inputStateKey);

EmailInputDatainputData=newEmailInputData

{

To=txtTo.Text,

Cc=txtCc.Text,

Bcc=txtBcc.Text,

Subject=txtSubject.Text,

Body=txtBody.Text

};

State.Add(inputStateKey,inputData);

base.OnNavigatedFrom(e);

}

protectedoverridevoidOnNavigatedTo(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedTofunctionofComposeEmailPage\t***");

if(State.ContainsKey(inputStateKey))

{

EmailInputDatainputData=(EmailInputData)State[inputStateKey];

txtTo.Text=inputData.To;

txtCc.Text=inputData.Cc;

txtBcc.Text=inputData.Bcc;

txtSubject.Text=inputData.Subject;

txtBody.Text=inputData.Body;

State.Remove(inputStateKey);

}

base.OnNavigatedTo(e);

}

  1. Toallowtheusertocomposeanemail,wewillusetheEmailComposeTask.EmailComposeTaskenablesanapplicationtolaunchthebuiltinemailcomposer,usingdatasuppliedbytheusertoinitializetheemailmessagecomposed.LocatethebtnCreateEmail_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnCreateEmail_Click(objectsender,RoutedEventArgse)

{

if(Microsoft.Devices.Environment.DeviceType==

Microsoft.Devices.DeviceType.Emulator)

{

MessageBox.Show("Thisoperationisnotsupportedintheemulator.Pleaseuseanactualdevice.");

return;

}

EmailComposeTaskcomposeTask=newEmailComposeTask();

composeTask.To=txtTo.Text;

composeTask.Cc=txtCc.Text;

composeTask.Bcc=txtBcc.Text;

composeTask.Subject=txtSubject.Text;

composeTask.Body=txtBody.Text;

composeTask.Show();

}

Note:NoticethatweputcodeatthetopofthehandlermethodtopreventthetaskfrombeingusedontheWindows®Phone7emulator.Wedidthissincethetaskcannotoperateproperlywithoutsettinganemailaccountinthedeviceandtheemulatordoesnotsupportsettingupanemailaccount.

Besuretosetupanemailaccountinyourdeviceforthenextstepstoworkproperly.

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheComposeEmailpageandfilloutthedesiredfields:

Figure11

Composinganemail

  1. Pressingthe“CreateEmail”buttonwilltakeyoutothephone’sbuilt-inemailcomposer,showinganemailwhichcontainsthedatasupplied.
  2. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  3. OpenShowMapPage.xaml.cs.
  4. Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:

C#

publicclassMapInputData

{

publicboolCenterOnCoordinate{get;set;}

publicstringLongitude{get;set;}

publicstringLatitude{get;set;}

publicstringLocation{get;set;}

publicstringZoomLevel{get;set;}

}

  1. OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethemapdataintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.

C#

protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedFromfunctionofShowMapPage\t***");

if(State.ContainsKey(inputStateKey))

State.Remove(inputStateKey);

MapInputDatainputData=newMapInputData

{

CenterOnCoordinate=radioCoordinate.IsChecked.Value,

Longitude=txtLongitude.Text,

Latitude=txtLatitude.Text,

Location=txtLocation.Text,

ZoomLevel=txtZoom.Text

};

State.Add(inputStateKey,inputData);

base.OnNavigatedFrom(e);

}

protectedoverridevoidOnNavigatedTo(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedTofunctionofShowMapPage\t***");

if(State.ContainsKey(inputStateKey))

{

MapInputDatainputData=(MapInputData)State[inputStateKey];

if(inputData.CenterOnCoordinate)

{

radioCoordinate.IsChecked=true;

}

else

{

radioLocation.IsChecked=true;

}

txtLocation.Text=inputData.Location;

txtLatitude.Text=inputData.Latitude;

txtLongitude.Text=inputData.Longitude;

txtZoom.Text=inputData.ZoomLevel;

State.Remove(inputStateKey);

}

base.OnNavigatedTo(e);

}

  1. Toallowtheusertoviewthemap,wewillusetheBingMapsTask.BingMapsTaskenablesanapplicationtolaunchthebuiltinmapsapplication,usingdatasuppliedbytheusertoinitializethemap’sposition.LocatethebtnShowMap_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnShowMap_Click(objectsender,RoutedEventArgse)

{

BingMapsTaskmapTask=newBingMapsTask();

if(radioCoordinate.IsChecked.Value)

{

doublelongitude;

doublelatitude;

if(!double.TryParse(txtLongitude.Text,outlongitude)||

Math.Abs(longitude)180)

{

MessageBox.Show("Pleasesupplyalongitudebetween-180and180");

return;

}

if(!double.TryParse(txtLatitude.Text,outlatitude)||

Math.Abs(latitude)90)

{

MessageBox.Show("Pleasesupplyalongitudebetween-90and90");

return;

}

mapTask.Center=newGeoCoordinate(latitude,longitude);

}

else

{

mapTask.SearchTerm=txtLocation.Text;

if(String.IsNullOrEmpty(mapTask.SearchTerm))

{

MessageBox.Show("Pleaseprovidealocation.");

return;

}

}

intzoomLevel;

if(!int.TryParse(txtZoom.Text,outzoomLevel)||zoomLevel1||

zoomLevel19)

{

MessageBox.Show("Pleasesupplyazoomlevelwhichisawholenumberbetween1and19.");

return;

}

mapTask.ZoomLevel=zoomLevel;

mapTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheShowMappageandselectalocationusingasearchtermoracoordinate:

Figure12

Selectingamaplocation

  1. Pressingthe“ShowMap”buttonwilltakeyoutothephone’sbuilt-inmapsapplication,centeredatthedesignatedlocation:

Figure13

Themapcenteredatthedesignatedlocation

Note:Ifyouhavenotyetallowedthephonetouselocationinformationyoumaybepromptedtodosonow.

  1. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  2. OpenDirectionsPage.xaml.cs.
  3. Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:

C#

publicclassDirectionsInputData

{

publicstringOrigin{get;set;}

publicstringDestination {get;set;}

}

  1. OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethedirectionsdataintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.

C#

protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedFromfunctionofDirectionsPage\t***");

if(State.ContainsKey(inputStateKey))

State.Remove(inputStateKey);

DirectionsInputDatainputData=newDirectionsInputData

{

Origin=txtOrigin.Text,

Destination=txtDestination.Text

};

State.Add(inputStateKey,inputData);

base.OnNavigatedFrom(e);

}

protectedoverridevoidOnNavigatedTo(NavigationEventArgse)

{

Debug.WriteLine("***\tInOnNavigatedTofunctionofDirectionsPage\t***");

if(State.ContainsKey(inputStateKey))

{

DirectionsInputDatainputData=

(DirectionsInputData)State[inputStateKey];

txtOrigin.Text=inputData.Origin;

txtDestination.Text=inputData.Destination;

State.Remove(inputStateKey);

}

base.OnNavigatedTo(e);

}

  1. Toallowtheusertoviewdirections,wewillusetheBingMapsDirectionsTask.BingMapsDirectionsTaskenablesanapplicationtolaunchthebuiltinmapsapplication,usingdatasuppliedbytheusertoshowdirectionsbetweentwolocations.LocatethebtnGetDirections_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnGetDirections_Click(objectsender,RoutedEventArgse)

{

BingMapsDirectionsTaskdirectionsTask=

newBingMapsDirectionsTask();

if(String.IsNullOrEmpty(txtOrigin.Text))

{

MessageBox.Show("Pleasesupplyanorigin.");

return;

}

if(String.IsNullOrEmpty(txtDestination.Text))

{

MessageBox.Show("Pleasesupplyadestination.");

return;

}

directionsTask.Start=newLabeledMapLocation(txtOrigin.Text,null);

directionsTask.End=newLabeledMapLocation(txtDestination.Text,

null);

directionsTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheDirectionspageandselecttwolocationsbetweenwhichyouwishtogetdirections:

Figure14

Selectingoriginanddestination

  1. Pressingthe“GetDirections”buttonwilltakeyoutothephone’sbuilt-inmapsapplication,showingthedesireddirections.
  2. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  3. Open ShareStatusPage.xaml.cs
  4. Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
  5. To share user’s status, we will useShareStatusTask. Locate the btnShareStatus_Click event handler and add the following code to the function body:

C#

if(txtStatus.Text.Length0)

{

ShareStatusTaskshareStatusTask=newShareStatusTask();

shareStatusTask.Status=txtStatus.Text;

shareStatusTask.Show();

}

else

MessageBox.Show("Cannotshareemptystatus.\nPleaseenteryourstatusandtryagain","ShareStatus-Error",MessageBoxButton.OK);

  1. Press F5 to compile and run the application.

Note: Status sharing functionality doesn’t workson emulator or if the device has no social accounts (Windows Live, Facebook, LinkedIn, Twitter) configured.

  1. Navigate to the Share Status page (in Social pivot page), provide new status and press the button to share it.
  2. Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
  3. Open ShareLinkPage.xaml.cs
  4. Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
  5. To share link, we will use ShareLinkTask. Locate the btnSharelink_Click event handler and add the following code to the function body:

C#

if(txtLink.Text.Length0Uri.IsWellFormedUriString(txtLink.Text,UriKind.Absolute))

{

ShareLinkTaskshareLinkTask=newShareLinkTask();

shareLinkTask.Message=txtMessage.Text;

shareLinkTask.Title=txtTitle.Text;

shareLinkTask.LinkUri=newUri(txtLink.Text,UriKind.Absolute);

shareLinkTask.Show();

}

else

MessageBox.Show("Cannotsharelinkorlinkisinvalid.\nPleasecheckyourinputandtryagain","ShareLink-Error",MessageBoxButton.OK);

  1. Press F5 to compile and run the application.

Note: Status sharing functionality doesn’t work on emulator or if the device has no social accounts (Windows Live, Facebook, LinkedIn, Twitter) configured.

  1. Navigate to the Share Link page (in Social pivot page), provide new link and press the button to share it.
  2. Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
  3. OpenShowMarketplacePage.xaml.cs.
  4. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.
  5. Toallowtheusertoviewthemarketplace,wewillusetheMarketplaceHubTask.MarketplaceHubTaskenablesanapplicationtolaunchthebuiltinmarketplacebrowser.LocatethebtnShowMarketplace_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnShowMarketplace_Click(objectsender,RoutedEventArgse)

{

MarketplaceHubTaskmarketplaceTask=newMarketplaceHubTask();

marketplaceTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. NavigatetotheShowmarketplacepageandpressthebuttontogotothemarketplacehub.
  3. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  4. Open ConnectionSettingsPage.xaml.cs
  5. Add the following code at the bottom of the page, before the end of namespace:

C#

publicclassConnectionSettings

{

publicstringName{get;set;}

publicConnectionSettingsTypeTypeID{get;set;}

}

  1. Now, add the following class-level variable which will be used as a source for page list box (at the top of ConnectionSettingsPage class):

C#

ListConnectionSettingsconnectionTypes;

  1. Add the list initialization code to the class:

C#

privatevoidInitializeConnectionTypes()

{

connectionTypes=newListConnectionSettings>();

connectionTypes.Add(newConnectionSettings(){TypeID=ConnectionSettingsType.AirplaneMode,Name="AirplaneMode"});

connectionTypes.Add(newConnectionSettings(){TypeID=ConnectionSettingsType.Bluetooth,Name="Bluetooth"});

connectionTypes.Add(newConnectionSettings(){TypeID=ConnectionSettingsType.Cellular,Name="Cellular"});

connectionTypes.Add(newConnectionSettings(){TypeID=ConnectionSettingsType.WiFi,Name="WiFi"});

lstConnectionTypes.DataContext=connectionTypes;

lstConnectionTypes.SelectedIndex=0;

}

  1. Call the function created before from class constructor - add the following code line afterInitializeComponent() function:

C#

InitializeConnectionTypes();

  1. To allow the user to open system connection settings, we will use the ConnectionSettingsTask. ConnectionSettingsTask enables an application to launch the built in connection settings application, showing specific settings that matches defined settings type. Locate the btnConnectionSettings_Click event handler function and add the following code to the function body:

C#

ConnectionSettingsTaskconnectionSettingsTask=newConnectionSettingsTask();

connectionSettingsTask.ConnectionSettingsType=
(lstConnectionTypes.SelectedItemasConnectionSettings).TypeID;

connectionSettingsTask.Show();

This code snippet defines which connection settings will be presented (defined by getting selection in the listbox) and starts the launcher.

  1. Press F5 to compile and run the application.
  2. Navigate to the Connection settings page at Settings hub, select connection settings type and press the button to go to the relevant system settings page.

Figure 15

Connection settings

  1. Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
  2. OpenSearchMarketplacePage.xaml.cs.
  3. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
  4. Toallowtheusertosearchthemarketplace,wewillusetheMarketplaceSearchTask.MarketplaceSearchTaskenablesanapplicationtolaunchthebuiltinmarketplaceapplication,showingonlycontentthatmatchesthesearchterm.LocatethebtnSearchMarketplace_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnSearchMarketplace_Click(objectsender,
RoutedEventArgse)

{

MarketplaceSearchTaskmarketplaceTask=newMarketplaceSearchTask();

marketplaceTask.SearchTerms=txtSearchTerm.Text;

marketplaceTask.Show();
}

  1. PressF5tocompileandruntheapplication.
  2. Navigatetothemarketplacesearchpageandenterasearchterm.
  3. Pressingthe“SearchMarketplace”buttonwilllaunchthebuilt-inmarketplaceapplicationandsearchforcontentusingthetermprovided:

Figure16

Contentmatchingthesearchterm

  1. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
  2. OpenMarketplaceDetailsPage.xaml.cs.
  3. Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.
  4. Toallowtheusertoviewthedetailsforamarketplaceapp,wewillusetheMarketplaceDetailTask.MarketplaceDetailTaskenablesanapplicationtolaunchthebuiltinmarketplaceapplicationtodisplayaspecificapp’sdetails.LocatethebtnMarketplaceDetails_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:

C#

privatevoidbtnMarketplaceDetails_Click(objectsender,

RoutedEventArgse)

{

MarketplaceDetailTaskmarketplaceTask=newMarketplaceDetailTask();

marketplaceTask.ContentIdentifier="35323b0f-84d8-df11-a844-00237de2db9e";

marketplaceTask.Show();

}

  1. PressF5tocompileandruntheapplication.
  2. Navigatetothemarketplacedetailspageandpressthebuttontoseethemarketplacedetailsfor“TheHarvest™”.

Note:Marketplaceandmultimediarelatedactionsdonotworkifthedeviceisconnectedtoacomputer,evenwhiledebugging.

  1. SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.

Thisstepconcludestheexercise.

Note:Thesolutionforthisexerciseislocatedatthislab’sSource\Endfolder.

Summary

ThislabillustratedtheuseoflaunchersinWindowsPhone7.Eachoftheapplication’smanypagesservesasanexampleforusingaspecificlauncher.Usingtheseexamplesyoushouldbeabletoeasilyutilizelaunchersinyourfutureapplications.

Page | 1

©2011 Microsoft Corporation. All rights reserved.