The Reminder
sample mirrors the alarm sample; however, the reminder sample demonstrates how to use the deep linking feature of reminders to allow editing of a reminder after it has been created.
The sample code for this section is located in the Reminders directory of the WPUnleashed.BackgroundAgents project in the BackgroundAgents solution.
Like the Alarm
sample, the ReminderView
page allows the user to enter the details of a new reminder and to set the reminder via an application bar button.
The ReminderViewModel
class contains various properties that correspond to the Reminder
class properties. Unlike the Alarm
class, however, the Reminder
class does not provide the ability to customize the sound effect of the notification.
The viewmodel contains two ICommand
properties: one for registering a new reminder and the other for displaying an existing reminder after it has been navigated to via a deep link. The backing fields for both commands are initialized in the viewmodel constructor, like so:
public ReminderViewModel()
{
reminderSetCommand = new DelegateCommand(obj => SetReminder());
loadReminderCommand = new DelegateCommand<string>(LoadReminder);
}
When executed, the ReminderSet
command calls the SetReminder
method, which creates a new Reminder
using the viewmodel’s property values. In addition, we construct a Uri
object that links back to the page if and when the user taps the reminder when it is displayed. See the following excerpt:
void SetReminder()
{
const string reminderUrlFormat = "/Reminders/ReminderView.xaml?Id={0}";
string navigationUrl = string.Format(reminderUrlFormat, ReminderName);
Uri navigationUri = new Uri(navigationUrl, UriKind.Relative);
Reminder reminder = new Reminder(ReminderName)
{
BeginTime = reminderBeginTime,
ExpirationTime = reminderExpirationTime,
Content = reminderContent,
RecurrenceType = reminderRecurrenceType,
NavigationUri = navigationUri,
Title = reminderTitle
};
if (ScheduledActionService.Find(reminder.Name) != null)
{
ScheduledActionService.Remove(reminder.Name);
}
ScheduledActionService.Add(reminder);
MessageService.ShowMessage("reminder set");
}
When the LoadReminderCommand
executes, the LoadReminder
method is called with the command parameter, which should be the name of a registered Reminder
. The ScheduledActionService
is used to retrieve the Reminder
by name. If it is located, the viewmodel’s properties are populated with the Reminder
values, as shown:
void LoadReminder(string name)
{
Reminder reminder = ScheduledActionService.Find(name) as Reminder;
if (reminder == null)
{
MessageService.ShowError("Reminder not found.");
return;
}
ReminderBeginTime = reminder.BeginTime;
ReminderContent = reminder.Content;
ReminderName = reminder.Name;
ReminderRecurrenceType = reminder.RecurrenceType;
ReminderTitle = reminder.Title;
}
LoadReminderCommand
is executed via the view’s OnNavigatedTo
method. When the user taps a reminder, the app starts with the ReminderView
displayed. The OnNavigatedTo
method extracts the Reminder
name using a key exposed by the viewmodel (see Listing 32.1).
The command is prevented from being executed more than once using an initialized
flag. OnNavigatedTo
may be called more than once if the app was tombstoned or a back navigation took place.
public partial class ReminderView : PhoneApplicationPage
{
bool initialized;
readonly ReminderViewModel viewModel;
public ReminderView()
{
InitializeComponent();
DataContext = viewModel = new ReminderViewModel();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (initialized)
{
return;
}
initialized = true;
string reminderId;
if (NavigationContext.QueryString.TryGetValue(
ReminderViewModel.IdQueryKey, out reminderId))
{
viewModel.LoadReminderCommand.Execute(reminderId);
}
}
}
The root grid within the view XAML contains a custom AppBar
that includes an AppBarIconButton
bound to the ReminderSetCommand
, like so:
<u:AppBar>
<u:AppBarIconButton
Command="{Binding ReminderSetCommand}"
Text="Set"
IconUri="/Images/ApplicationBarIcons/Check.png" />
</u:AppBar>
The view allows the user to set the properties of a new Reminder
or to edit the properties of an existing Reminder
.
<StackPanel Grid.Row="1" Margin="12,0,12,0">
<TextBlock Text="name" />
<TextBox Text="{Binding ReminderName, Mode=TwoWay}" />
<TextBlock Text="title" />
<TextBox Text="{Binding ReminderTitle, Mode=TwoWay}" />
<TextBlock Text="content" />
<TextBox Text="{Binding ReminderContent, Mode=TwoWay}" />
<StackPanel Orientation="Horizontal">
<StackPanel>
<TextBlock Text="begin time" />
<toolkit:TimePicker
Value="{Binding ReminderBeginTime, Mode=TwoWay}" />
</StackPanel>
<StackPanel>
<TextBlock Text="expires" />
<toolkit:DatePicker
Value="{Binding ReminderExpirationTime, Mode=TwoWay}" />
</StackPanel>
</StackPanel>
<toolkit:ListPicker
Header="recurrence interval"
ItemsSource="{Binding RecurrenceIntervals}"
SelectedItem="{Binding ReminderRecurrenceType, Mode=TwoWay}" />
</StackPanel>
Figure 32.4 shows the set reminder view, which allows the user to enter the new reminder information.
After the reminder has been set, and the begin time arrives, a dialog is presented to the user, displaying the reminder information (see Figure 32.5).
Tapping the reminder launches the app and automatically causes the app to navigate to the NavigateUri
property of the Reminder
, which allows the Reminder
to be modified and reregistered.
Alarms and reminders offer a simple way to add notification support to your app. The next section looks at scheduled tasks and how they offer the capability to perform application logic in the background.
18.188.200.164