Reminder Registration
Reminder registration is done in much the same way as for Alarm
objects. The reminder is instantiated and then registered with the ScheduledActionService
.
With reminders, however, you are able to provide a URI that allows you
to deep link back to a particular page within the app, as shown in the
following excerpt:
Reminder reminder = new Reminder("ReminderName")
{
BeginTime = DateTime.Now.AddMinutes(5),
ExpirationTime = DateTime.Now.AddDays(5),
Content = "Your daily reminder.",
RecurrenceType = RecurrenceInterval.Daily,
NavigationUri = new Uri("/ReminderView.xaml?Id=ReminderName",
UriKind.Relative),
Title = reminderTitle
};
if (ScheduledActionService.Find(reminder.Name) != null)
{
ScheduledActionService.Remove(reminder.Name);
}
ScheduledActionService.Add(reminder);
The following section looks at creating a page that allows you to experiment with reminders.
Reminder Sample
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 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.
LISTING 1. ReminderView
Class
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 4 shows the set reminder view, which allows the user to enter the new reminder information.
FIGURE 4 Set Reminder view.
After the reminder has
been set, and the begin time arrives, a dialog is presented to the
user, displaying the reminder information (see Figure 5).
FIGURE 5 A reminder can be snoozed or dismissed by the user.
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.