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.
- OpenSavePhoneNumberPage.xaml.cs.
- AddthefollowingcodetotheSavePhoneNumberPageclass:
C#
//Regexpatternsprovidedby
conststringphoneNumberPattern=@"^([0-9](|-)?)?(\(?[0-9]{3}\)?|[0-9]{3})(|-)?([0-9]{3}(|-)?[0-9]{4}|[a-zA-Z0-9]{7})$";
- Addthefollowingusingstatements:
C#
usingSystem.Text.RegularExpressions;
usingMicrosoft.Phone.Tasks;
usingSystem.Diagnostics;
usingSystem.Windows.Navigation;
- 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);
}
- AddtheinputstatekeyconstanttotheSavePhoneNumberPageclass.
C#
conststringinputStateKey="input";
- AddaSavePhoneNumberTaskvariabletotheSavePhoneNumberPageclass.
C#
SavePhoneNumberTasksavePhoneNumberTask;
- AddthefollowinghighlightedcodetoinitializethesavePhoneNumberTaskvariableintheclassconstructorandoutputdebuginformation.
C#
publicSavePhoneNumberPage()
{
InitializeComponent();
Debug.WriteLine("***\tInconstructorofSavePhoneNumberPage\t***");
savePhoneNumberTask=newSavePhoneNumberTask();
savePhoneNumberTask.Completed+=newEventHandlerTaskEventArgs>(savePhoneNumberTask_Completed);
}
- 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);
}
- 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);
}
}
- PressF5tocompileandruntheapplication.
- NavigatetotheSavePhoneNumberpageandtypeavalidphonenumber.
- ToexecutetheLauncherclickSavePhoneNumber.
- AddthephonenumbertoaneworexistingcontactusingthestandardWindows®Phone7interface:
Figure1
Addingaphonenumbertoexistingornewcontact
- Optionally,givethecontactaname.
- SavethecontactandclickBack():
Figure2
Launcherreturnnotification
Note:TheinsertedphonenumbershouldappearintheinputtextboxeventhoughtheapplicationwassenttothebackgroundduringthePhoneSaveTaskoperation.Analyzethedebugoutputtogainabetterunderstandingofthisprocess.
- Repeatthissteptoaddanewcontact.
Note:Theemulatorpreservescontactsdataonlywhenitisrunning.Pleasedonotclosetheemulatorbetweenthesteps.Thisenablesviewingthecontact’sinformationlateroninthelab.
- PressSHIFT+F5tostopthedebuggerandreturntoeditingmode.
- OpenSaveEmailAddressPage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavetheemailaddressintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
- AddaSaveEmailAddressTaskvariabletotheSaveEmailAddressPageclass.
C#
SaveEmailAddressTasksaveEmailAddressTask;
- AddthefollowinghighlightedcodetoinitializethesaveEmailAddressTaskvariableintheclassconstructor.
C#
publicSaveEmailAddressPage()
{
InitializeComponent();
Debug.WriteLine("***\tInconstructorofSaveEmailAddressPage\t***");
saveEmailAddressTask=newSaveEmailAddressTask();
saveEmailAddressTask.Completed+=newEventHandlerTaskEventArgs>(saveEmailAddressTask_Completed);
}
- 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);
}
- 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);
}
}
- PressF5tocompileandruntheapplication.
- NavigatetotheSaveEmailpageandtypeavalidemailaddress.
- ToexecutetheLauncher,clickSaveEmailAddress.
- AddtheemailaddresstoaneworexistingcontactusingthestandardWindows®Phone7interface:
Figure3
Addinganemailaddresstoexistingornewcontact
- SavethecontactandclickBack():
- PressSHIFT+F5tostopthedebuggerandreturntoeditingmode.
- OpenSearchTaskPage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned:
- ToexecutethesearchfunctionalitythislabusesSearchTask.SearchTaskenablesanapplicationtolaunchtheWebSearchapplication.LocatethebtnSearch_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnSearch_Click(objectsender,RoutedEventArgse)
{
SearchTasksearchTask=newSearchTask();
searchTask.SearchQuery=txtInput.Text;
searchTask.Show();
}
- Compileandruntheapplication.
- NavigatetotheSearchpageandinputasearchquery:
Figure4
SearchPage
- ClickSearchEverywhere.
- It is possible, that the first search execution displays a screen asking toallowlocationinformationusage.ClickAllow.
- TheemulatorconnectstotheWebandbringsbackthedefinedqueryresults:
Figure5
WebResults
- PressSHIFT+F5tostopthedebuggingandreturntoeditingmodeinVisualStudio.
- OpenWebSearchPage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
- SilverlighthasaWebBrowsercontrolthatcouldbeusedasanyotherSilverlightcontrolintheapplication.InadditionWindowsPhonehasaWebBrowserlauncherenablingInternetExplorertobestarteddirectlyfromtheapplication.Touseit,thislabusesWebBrowserTask.WebBrowserTaskenablesanapplicationtolaunchtheWebbrowserapplication.LocatethebtnGo_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnGo_Click(objectsender,RoutedEventArgse)
{
WebBrowserTaskwebBrowserTask=newWebBrowserTask();
conststringurl="
webBrowserTask.URL=string.Format(url,txtInput.Text);
webBrowserTask.Show();
}
- PressF5tocompileandruntheapplication.
- NavigatetotheSearchwithBingpageandinputasearchquery.
- TheLauncherstartsInternetExplorerandnavigatestoBingwebpage:
Figure6
Windows®Phone7.1IE
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- OpenVideoPlayerPage.xaml.cs.
- OverridetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.
C#
protectedoverridevoidOnNavigatedFrom(NavigationEventArgse)
{
Debug.WriteLine("***\tInOnNavigatedFromfunctionofVideoPlayerPage\t***");
base.OnNavigatedFrom(e);
}
protectedoverridevoidOnNavigatedTo(NavigationEventArgse)
{
Debug.WriteLine("***\tInOnNavigatedTofunctionofVideoPlayerPage\t***");
base.OnNavigatedTo(e);
}
- FromtheSource\Assetsfolderofthislab,addanexistingvideofiletotheproject’sMediafolder.
- AttheAddExistingItemdialogbrowsetotheAssetsfolderofthislab,selectthevideofile,andfromtheAddbuttondropdownlistselectAddAsLink.
Figure7
Selectingthevideofile
- MakesurethevideofilewasaddedasaContentresource.Tocheckit,clickontheaddedfileinSolutionExplorerandpressF4toshowthefileproperties.
Figure8
CheckingtheBuildActionoftheaddedvideofile
- 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();
}
- PressF5tocompileandruntheapplication.
- NavigatetotheVideoPlayerpageandplaythevideo.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- OpenSaveRingtonePage.xaml.cs.
- Addthefollowingusingstatementstotheclass:
C#
usingSystem.IO.IsolatedStorage;
usingSystem.IO;
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosupplydebuginformationwhentheapplication istombstoned.
- Addasoundfilethatwillserveasaringtonetotheproject.Performsteps48-50inclusiveasecondtime,butinsteadofadding“Bear.wmv”add“Ring.mp3”.
- Addthefollowinghighlightedcodetocreatethedebuginformationintheclassconstructor,andtodeploythesoundfilethatwewilluseasthenewringtonetoisolatedstorage.
C#
publicSaveRingtonePage()
{
InitializeComponent();
Debug.WriteLine("***\tInconstructorofSaveRingtonePage\t***");
PlaceAssetInIsolatedStorage();
}
- 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;
}
}
- Toallowtheusertoassociatearingtonewithacontact,wewillusetheSaveRingtoneTask.LocatethebtnSaveRingtone_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnSaveRingtone_Click(objectsender,RoutedEventArgse)
{
SaveRingtoneTaskringtoneTask=newSaveRingtoneTask();
ringtoneTask.Source=newUri("isostore:/Ring.mp3",UriKind.Absolute);
ringtoneTask.Show();
}
- PressF5tocompileandruntheapplication.
- Navigatetothe“SaveRingtone”pageandpressthescreensonlybutton: “Save Ringtone”
- Itwilltakeyoutothephone’sbuilt-inringtonesavingscreen,allowingyoutospecifyafilenameforthesavedringtoneandtosetitastheactiveringtone:
Figure9
Thebuilt-inringtonesavingscreen
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- Open SaveContactPage.xaml.cs.
- Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
- 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();
}
- Press F5 to compile and run the application.
Figure 10
Saving contact information
- Navigate to the Save New Contact page, provide required information and click “Save New Contact” button. Save the new contact and click Back ().
- Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
- OpenComposeEmailPage.xaml.cs.
- Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:
C#
publicclassEmailInputData
{
publicstringTo{get;set;}
publicstringCc{get;set;}
publicstringBcc{get;set;}
publicstringSubject{get;set;}
publicstringBody{get;set;}
}
- 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);
}
- 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.
- PressF5tocompileandruntheapplication.
- NavigatetotheComposeEmailpageandfilloutthedesiredfields:
Figure11
Composinganemail
- Pressingthe“CreateEmail”buttonwilltakeyoutothephone’sbuilt-inemailcomposer,showinganemailwhichcontainsthedatasupplied.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- OpenShowMapPage.xaml.cs.
- Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:
C#
publicclassMapInputData
{
publicboolCenterOnCoordinate{get;set;}
publicstringLongitude{get;set;}
publicstringLatitude{get;set;}
publicstringLocation{get;set;}
publicstringZoomLevel{get;set;}
}
- 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);
}
- 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();
}
- PressF5tocompileandruntheapplication.
- NavigatetotheShowMappageandselectalocationusingasearchtermoracoordinate:
Figure12
Selectingamaplocation
- Pressingthe“ShowMap”buttonwilltakeyoutothephone’sbuilt-inmapsapplication,centeredatthedesignatedlocation:
Figure13
Themapcenteredatthedesignatedlocation
Note:Ifyouhavenotyetallowedthephonetouselocationinformationyoumaybepromptedtodosonow.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- OpenDirectionsPage.xaml.cs.
- Usethefollowingcodetoplaceanadditionalclassinthefile.Wewillusethisclasstostoreinputdataprovidedbytheuser:
C#
publicclassDirectionsInputData
{
publicstringOrigin{get;set;}
publicstringDestination {get;set;}
}
- 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);
}
- 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();
}
- PressF5tocompileandruntheapplication.
- NavigatetotheDirectionspageandselecttwolocationsbetweenwhichyouwishtogetdirections:
Figure14
Selectingoriginanddestination
- Pressingthe“GetDirections”buttonwilltakeyoutothephone’sbuilt-inmapsapplication,showingthedesireddirections.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- Open ShareStatusPage.xaml.cs
- Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
- 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);
- 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.
- Navigate to the Share Status page (in Social pivot page), provide new status and press the button to share it.
- Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
- Open ShareLinkPage.xaml.cs
- Note we overrode the OnNavigatedFrom and OnNavigatedTo functions in order to add debug information when the application is being tombstoned.
- 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);
- 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.
- Navigate to the Share Link page (in Social pivot page), provide new link and press the button to share it.
- Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
- OpenShowMarketplacePage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.
- Toallowtheusertoviewthemarketplace,wewillusetheMarketplaceHubTask.MarketplaceHubTaskenablesanapplicationtolaunchthebuiltinmarketplacebrowser.LocatethebtnShowMarketplace_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnShowMarketplace_Click(objectsender,RoutedEventArgse)
{
MarketplaceHubTaskmarketplaceTask=newMarketplaceHubTask();
marketplaceTask.Show();
}
- PressF5tocompileandruntheapplication.
- NavigatetotheShowmarketplacepageandpressthebuttontogotothemarketplacehub.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- Open ConnectionSettingsPage.xaml.cs
- Add the following code at the bottom of the page, before the end of namespace:
C#
publicclassConnectionSettings
{
publicstringName{get;set;}
publicConnectionSettingsTypeTypeID{get;set;}
}
- 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;
- 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;
}
- Call the function created before from class constructor - add the following code line afterInitializeComponent() function:
C#
InitializeConnectionTypes();
- 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.
- Press F5 to compile and run the application.
- 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
- Switch back to Visual Studio and press SHIFT+F5 to stop the debugger.
- OpenSearchMarketplacePage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertosavethesearchtermintothepage'sstatesoitcanbedisplayedagainincasetheapplicationhasbeentombstoned.
- Toallowtheusertosearchthemarketplace,wewillusetheMarketplaceSearchTask.MarketplaceSearchTaskenablesanapplicationtolaunchthebuiltinmarketplaceapplication,showingonlycontentthatmatchesthesearchterm.LocatethebtnSearchMarketplace_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnSearchMarketplace_Click(objectsender,
RoutedEventArgse)
{
MarketplaceSearchTaskmarketplaceTask=newMarketplaceSearchTask();
marketplaceTask.SearchTerms=txtSearchTerm.Text;
marketplaceTask.Show();
}
- PressF5tocompileandruntheapplication.
- Navigatetothemarketplacesearchpageandenterasearchterm.
- Pressingthe“SearchMarketplace”buttonwilllaunchthebuilt-inmarketplaceapplicationandsearchforcontentusingthetermprovided:
Figure16
Contentmatchingthesearchterm
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
- OpenMarketplaceDetailsPage.xaml.cs.
- Note we overrodetheOnNavigatedFromandOnNavigatedTofunctionsinordertoadddebuginformationwhentheapplicationisbeingtombstoned.
- Toallowtheusertoviewthedetailsforamarketplaceapp,wewillusetheMarketplaceDetailTask.MarketplaceDetailTaskenablesanapplicationtolaunchthebuiltinmarketplaceapplicationtodisplayaspecificapp’sdetails.LocatethebtnMarketplaceDetails_Clickeventhandlerfunctionandaddthefollowingcodetothefunctionbody:
C#
privatevoidbtnMarketplaceDetails_Click(objectsender,
RoutedEventArgse)
{
MarketplaceDetailTaskmarketplaceTask=newMarketplaceDetailTask();
marketplaceTask.ContentIdentifier="35323b0f-84d8-df11-a844-00237de2db9e";
marketplaceTask.Show();
}
- PressF5tocompileandruntheapplication.
- Navigatetothemarketplacedetailspageandpressthebuttontoseethemarketplacedetailsfor“TheHarvest™”.
Note:Marketplaceandmultimediarelatedactionsdonotworkifthedeviceisconnectedtoacomputer,evenwhiledebugging.
- SwitchbacktoVisualStudioandpressSHIFT+F5tostopthedebugger.
Thisstepconcludestheexercise.
Note:Thesolutionforthisexerciseislocatedatthislab’sSource\Endfolder.
Summary
ThislabillustratedtheuseoflaunchersinWindowsPhone7.Eachoftheapplication’smanypagesservesasanexampleforusingaspecificlauncher.Usingtheseexamplesyoushouldbeabletoeasilyutilizelaunchersinyourfutureapplications.
Page | 1
©2011 Microsoft Corporation. All rights reserved.