This chapter is from the book
The Code-Behind
Listing 3.2 contains the code-behind, which is pretty short, especially compared to the preceding chapter. Its job is to persist what the user has typed in, launch the Phone app, and provide a few subtle text box behaviors.
Listing 3.2. MainPage.xaml.cs—The Code-Behind for "In Case of Emergency"
using
System.Windows;using
System.Windows.Controls;using
System.Windows.Input;using
System.Windows.Navigation;using
Microsoft.Phone.Controls;using
Microsoft.Phone.Tasks;namespace
WindowsPhoneApp {public partial class
MainPage
:PhoneApplicationPage
{// Remember what is typed in the text boxes, otherwise this app is pointless!
Setting
<string
> savedContactName =new
Setting
<string
>("ContactName"
,""
);Setting
<string
> savedPhoneNumber =new
Setting
<string
>("PhoneNumber"
,""
);Setting
<string
> savedOwnerName =new
Setting
<string
>("OwnerName"
,""
);Setting
<string
> savedMedicalNotes =new
Setting
<string
>("MedicalNotes"
,""
);public
MainPage() { InitializeComponent(); }protected override void
OnNavigatedTo(NavigationEventArgs
e) {base
.OnNavigatedTo(e);// Restore saved text box contents when entering this page
ContactNameTextBox.Text =this
.savedContactName.Value; PhoneNumberTextBox.Text =this
.savedPhoneNumber.Value; OwnerNameTextBox.Text =this
.savedOwnerName.Value; MedicalNotesTextBox.Text =this
.savedMedicalNotes.Value; }protected override void
OnNavigatingFrom(NavigatingCancelEventArgs
e) {base
.OnNavigatingFrom(e);// Persist text box contents when leaving this page for any reason
this
.savedContactName.Value = ContactNameTextBox.Text;this
.savedPhoneNumber.Value = PhoneNumberTextBox.Text;this
.savedOwnerName.Value = OwnerNameTextBox.Text;this
.savedMedicalNotes.Value = MedicalNotesTextBox.Text; }void
TapHereToCall_MouseLeftButtonUp(object
sender,MouseButtonEventArgs
e) {// Launch the Phone app with the contact name and phone number
PhoneCallTask
phoneLauncher =new
PhoneCallTask
(); phoneLauncher.DisplayName =this
.ContactNameTextBox.Text; phoneLauncher.PhoneNumber =this
.PhoneNumberTextBox.Text;if
(phoneLauncher.PhoneNumber.Length == 0)MessageBox
.Show("There is no emergency contact phone number to call."
,"Phone"
,MessageBoxButton
.OK);else
phoneLauncher.Show(); }void
TextBox_GotFocus(object
sender,RoutedEventArgs
e) {// Select all text so it can be cleared with one keystroke
(sender as TextBox).SelectAll(); }void
TextBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) {if
(sender ==this
.ContactNameTextBox)this
.PhoneNumberTextBox.Focus();else
if
(sender ==this
.PhoneNumberTextBox)// hardware keyboard only
this
.OwnerNameTextBox.Focus();else
if
(sender ==this
.OwnerNameTextBox)this
.MedicalNotesTextBox.Focus(); e.Handled =true
; } } } }
Notes:
- The four Setting members and the OnNavigatedTo/OnNavigatedFrom methods exist to remember what the user has typed in the four text boxes for subsequent uses of the app.
- The tap event handler for the "tap here to call" label (TapHereToCall_MouseLeftButtonUp) uses the phone launcher (the PhoneCallTask class) to make a phone call with whatever phone number has been typed into PhoneNumberTextBox (and whatever display name has been typed into ContactNameTextBox). It's okay if the display name is an empty string, but if the phone number is an empty string then the call to Show silently does nothing. Therefore, we check for this error condition and explain to the user why the phone wasn't launched. The full set of Windows Phone launchers are examined in Volume II of this book series, but you can see the phone launcher is straightforward to use. Note that users are prompted before any phone call is made, and they have the power to cancel the phone call. This prompt is shown at the end of the chapter.
- The GotFocus event handler shared by the first three text boxes (TextBox_GotFocus) selects (highlights) all the text inside it, as shown in Figure 3.9. This is done by most text boxes in Windows Phone apps (such as the URL box in Internet Explorer) so the user can delete all the text by pressing backspace once, or by simply starting to type something new. For the rare case of the user wanting to append text to the existing text, the user must first tap the text box to remove the selection. When the text box is empty, the call to SelectAll has no effect, which is exactly the behavior we want. This handler is not attached to the multiline text box, because it's more likely that the user would tap on it to append text rather than replace it all.
Figure 3.9 When one of the first three text boxes has existing text and gets focus, its text becomes selected thanks to the implementation of TextBox_GotFocus.
- The KeyDown event handler (TextBox_KeyDown) provides another convenient behavior: moving focus to the next text box when the Enter key is pressed. (Otherwise, pressing Enter in a single-line text box does nothing, which is a weird experience.) To do this, it determines which text box raised the event so it knows which one to give focus. Setting KeyEventArgs.Handled to true is important to prevent the keystroke from getting processed any further. Without this, when MedicalNotesTextBox is given focus, it would also receive the Enter keystroke (even though it was pressed when OwnerNameTextBox had focus) and an unwanted newline would appear in it.
- For the sake of navigation, pressing Enter when the last text box has focus would ideally dismiss the on-screen keyboard. However, because it's a multiline text box, it is not appropriate to take any custom action when Enter is pressed. That is why we didn't attach TextBox_KeyDown to MedicalNotesTextBox's KeyDown event in Listing 3.1.
- Navigating from the first to last text box via the Enter key doesn't entirely work with the on-screen keyboard because it doesn't have an Enter key when PhoneNumberTextBox has focus (due to its use of the PhoneNumber input scope)! With a hardware keyboard, this is not an issue, so the focus can keep moving without getting "stuck," thanks to the logic inside TextBox_KeyDown.