The ApplicatonBar in Jot defines four buttons:
for adding a new page, going to the previous page, going to the next
page, and deleting the current page. (If the current page is the only
page, then only the strokes are deleted from the page.) Each button has its own Click handler:
Example 1. Silverlight Project: Jot File: MainPage.xaml (excerpt)
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="appbarAddButton" IconUri="/Images/appbar.add.rest.png" Text="add page" Click="OnAppbarAddClick" />
<shell:ApplicationBarIconButton x:Name="appbarLastButton" IconUri="/Images/appbar.back.rest.png" Text="last page" Click="OnAppbarLastClick" />
<shell:ApplicationBarIconButton x:Name="appbarNextButton" IconUri="/Images/appbar.next.rest.png" Text="next page" Click="OnAppbarNextClick" />
<shell:ApplicationBarIconButton x:Name="appbarDeleteButton" IconUri="/Images/appbar.delete.rest.png" Text="delete page" Click="OnAppbarDeleteClick" /> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="swap colors" Click="OnAppbarSwapColorsClick" />
<shell:ApplicationBarMenuItem Text="light stroke width" Click="OnAppbarSetStrokeWidthClick" />
<shell:ApplicationBarMenuItem Text="medium stroke width" Click="OnAppbarSetStrokeWidthClick" />
<shell:ApplicationBarMenuItem Text="heavy stroke width" Click="OnAppbarSetStrokeWidthClick" /> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
|
A menu is also included with a collection of ApplicationBarMenuItem objects in the MenuItems property element. The menu items are displayed when you press the ellipsis on the ApplicationBar.
They consist solely of short text strings in lower-case. (You should
keep menu items to five or fewer, and keep the text to a maximum of 20
characters or so.)
The first menu item (to swap the colors) has its own Click handler; the other three share a Click handler.
Here are the Click handlers for the four buttons:
Example 2. Silverlight Project: Jot File: MainPage.xaml.cs (excerpt)
void OnAppbarAddClick(object sender, EventArgs args) { StrokeCollection strokes = new StrokeCollection(); appSettings.PageNumber += 1; appSettings.StrokeCollections.Insert(appSettings.PageNumber, strokes); inkPresenter.Strokes = strokes; TitleAndAppbarUpdate(); }
void OnAppbarLastClick(object sender, EventArgs args) { appSettings.PageNumber -= 1; inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber]; TitleAndAppbarUpdate(); }
void OnAppbarNextClick(object sender, EventArgs args) { appSettings.PageNumber += 1; inkPresenter.Strokes = appSettings.StrokeCollections[appSettings.PageNumber]; TitleAndAppbarUpdate(); }
void OnAppbarDeleteClick(object sender, EventArgs args) { MessageBoxResult result = MessageBox.Show("Delete this page?", "Jot", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK) { if (appSettings.StrokeCollections.Count == 1) { appSettings.StrokeCollections[0].Clear(); } else { appSettings.StrokeCollections.RemoveAt(appSettings.PageNumber);
if (appSettings.PageNumber == appSettings.StrokeCollections.Count) appSettings.PageNumber -= 1;
inkPresenter.Strokes = appSettings.StrokeCollections[appSettings. PageNumber]; } TitleAndAppbarUpdate(); } }
|
The only one just a little
complex is the deletion of a page, but notice that it begins by asking
for a confirmation from the user with a call to MessageBox.Show! A message box seems very archaic in this context, but the most important characteristic of MessageBox.Show
on the phone is that it works with a minimum of hassle. If you just
need to inform the user of something with an OK button, or if you need
to ask a question with OK and Cancel, nothing beats it.
The message box is displayed at the top of the screen and disables the rest of the application until you make it go away:
The four menu items are handled here:
Example 3. Silverlight Project: Jot File: MainPage.xaml.cs (excerpt)
void OnAppbarSwapColorsClick(object sender, EventArgs args) { Color foreground = appSettings.Background; appSettings.Background = appSettings.Foreground; appSettings.Foreground = foreground; inkPresenter.Background = new SolidColorBrush(appSettings.Background);
foreach (StrokeCollection strokeCollection in appSettings.StrokeCollections) foreach (Stroke stroke in strokeCollection) stroke.DrawingAttributes.Color = appSettings.Foreground; } void OnAppbarSetStrokeWidthClick(object sender, EventArgs args) { ApplicationBarMenuItem item = sender as ApplicationBarMenuItem;
if (item.Text.StartsWith("light")) appSettings.StrokeWidth = 1;
else if (item.Text.StartsWith("medium")) appSettings.StrokeWidth = 3;
else if (item.Text.StartsWith("heavy")) appSettings.StrokeWidth = 5; }
|
When swapping colors, the new colors must be saved in application settings, but the existing colors of all the Stroke objects on every page must also be changed. Fortunately, it’s just a couple nested foreach loops.
The OnAppbarSetStrokeWidthClick method accommodates three related menu items. Notice that the sender object is the particular ApplicationBarMenuItem that’s been clicked. The logic here is simple, but it depends on the Text
properties of the three items. You might prefer using a technique that
is independent of that text, such as three separate handlers.
You’ve already seen several references to TitleAndAppbarUpdate, the final method in the MainPage code-behind file. Here it is:
Example 4. Silverlight Project: Jot File: MainPage.xaml.cs (excerpt)
void TitleAndAppbarUpdate() { pageInfoTitle.Text = String.Format(" - PAGE {0} OF {1}", appSettings.PageNumber + 1, appSettings.StrokeCollections.Count);
appbarLastButton.IsEnabled = appSettings.PageNumber > 0; appbarNextButton.IsEnabled = appSettings.PageNumber < appSettings.StrokeCollections.Count - 1; appbarDeleteButton.IsEnabled = (appSettings.StrokeCollections.Count > 1) || (appSettings.StrokeCollections[0].Count > 0); }
|
The last three statements disable various buttons on the ApplicationBar
if they aren’t valid. (The handlers for the buttons rely on the fact
that they won’t be called if the option is invalid.) These statements
are able to reference the names assigned to the three buttons in the
XAML file because I reassigned those names in the MainPage constructor:
Example 5. Silverlight Project: Jot File: MainPage.xaml.cs (excerpt)
public MainPage() { InitializeComponent(); . . . appbarLastButton = this.ApplicationBar.Buttons[1] as ApplicationBarIconButton; appbarNextButton = this.ApplicationBar.Buttons[2] as ApplicationBarIconButton; appbarDeleteButton = this.ApplicationBar.Buttons[3] as ApplicationBarIconButton; . . . }
|
The first statement in TitleAndAppbarUpdate references a TextBlock that I added to the application title in the XAML file:
Example 6. Silverlight Project: Jot File: MainPage.xaml (excerpt)
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12" Orientation="Horizontal"> <TextBlock x:Name="ApplicationTitle" Text="JOT" Style="{StaticResource PhoneTextNormalStyle}" Margin="12 0 0 0" /> <TextBlock Name="pageInfoTitle" Style="{StaticResource PhoneTextNormalStyle}" Margin="0" /> </StackPanel>
|
Jot is one program that is not enabled for landscape mode. Once you’ve jotted something on an InkPresenter
of a particular size and aspect ratio, you don’t want it flipped around
so that some of what you’ve done is now off-screen. But Jot is also a
program you can use sideways without the program itself being aware of
the orientation change: