Debugging Scheduled Tasks
Debugging a task agent is done by calling the ScheduledActionService.LaunchForTest
method. Calling LaunchForTest
is a way of forcing the OS to run your task agent. LaunchForTest
accepts two parameters: the name of the scheduled task and a TimeSpan
that indicates the delay before the task agent is invoked. By specifying TimeSpan.Zero
, the task agent is invoked immediately.
With the TestAgentCommand
wired up to the UI, you can instruct the OS to launch the task agent, allowing you to step into the task agent’s OnInvoke
method. The task agent for the sample is discussed later in this section.
The viewmodel relies on a custom IDeviceProperties
interface, which allows the viewmodel to retrieve the Windows Live
anonymous ID.
TodoListView XAML
The TodoListView
XAML contains a LongListSelector
that is bound to the GroupedTodoItems
property of the viewmodel (see Listing 5). The LongListSelector
’s ItemTemplate
uses a TextBlock
to display the Description
property of each TodoItem
. When the user taps the description, the EditItemCommand
is executed, and the Id
of the TodoItem
is passed as a command parameter.
The LongListSelector's GroupHeaderTemplate
contains a Border
whose background is determined by the Overdue
property of the group key, which is a DateGroupingKey
instance.
LISTING 5. TodoListView.xaml (excerpt)
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector
ItemsSource="{Binding GroupedTodoItems}"
IsGroupingEnabled="True"
Background="Transparent"
Height="600">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}"
Margin="12,10,0,10"
Style="{StaticResource PhoneTextLargeStyle}"
c:Commanding.Event="Tap"
c:Commanding.Command="{Binding DataContext.EditItemCommand,
ElementName=page}"
c:Commanding.CommandParameter="{Binding Id}" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
<phone:LongListSelector.GroupHeaderTemplate>
<DataTemplate>
<Border Background="Transparent">
<Border Background="{Binding Key.Overdue,
Converter={StaticResource BooleanToBrushConverter}}"
Padding="5"
HorizontalAlignment="Left"
Margin="0,10,0,0">
<TextBlock
Text="{Binding Key.DateTime, StringFormat=\{0:d\}}"
Foreground="{StaticResource PhoneForegroundBrush}"
Style="{StaticResource PhoneTextLargeStyle}"
VerticalAlignment="Bottom" />
</Border>
</Border>
</DataTemplate>
</phone:LongListSelector.GroupHeaderTemplate>
</phone:LongListSelector>
</StackPanel>
The custom BooleanToBrushConverter
is used to transform the Overdue
property of type bool
to a brush.
The BooleanToBrushConverter
is defined as a page resource as shown:
<phone:PhoneApplicationPage.Resources>
<ValueConverters:BooleanToBrushConverter
x:Name="BooleanToBrushConverter"
BrushIfTrue="Red"
BrushIfFalse="Blue" />
</phone:PhoneApplicationPage.Resources>
Overdue groups are shown with a red header, and regular groups have a blue header (see Figure 1).
FIGURE 1. To-do items are grouped according to when they are due to expire.
The custom AppBar
for the page includes an AppBarHyperlinkButton
, which takes the user to the TodoItemView
page and allows the user to create a new to-do item. The other viewmodel commands are bound to AppBarMenuItems
, as shown:
<u:AppBar>
<u:AppBarHyperlinkButton
NavigateUri="/TodoList/TodoItemView.xaml"
Text="New"
IconUri="/Images/ApplicationBarIcons/Add.png" />
<u:AppBar.MenuItems>
<u:AppBarMenuItem
Command="{Binding BackupDatabaseCommand}"
Text="Backup" />
<u:AppBarMenuItem
Command="{Binding RestoreDatabaseCommand}"
Text="Restore" />
<u:AppBarMenuItem
Command="{Binding TestAgentCommand}"
Text="test agent" />
</u:AppBar.MenuItems>
</u:AppBar>
You have seen how the list of to-do items is displayed; the next section examines how new to-do items are created.
TodoItemView and ViewModel
The TodoItemView
allows the user to perform the following three tasks:
- Create a new todo item
- Update an existing todo item
- Delete a todo item
The TodoItemViewModel
constructor receives the ITodoService
, initializes commands, and registers persistent state, as shown:
public TodoItemViewModel(ITodoService todoService)
{
this.todoService = ArgumentValidator.AssertNotNull(
todoService, "todoService");
saveCommand = new DelegateCommand<bool>(SaveItem);
loadItemCommand = new DelegateCommand<int>(LoadItem);
deleteCommand = new DelegateCommand(obj => DeleteItem());
RegisterStatefulProperty(ApplicationStateType.Transient,
() => TodoDescription);
RegisterStatefulProperty(ApplicationStateType.Transient,
() => TodoDueDate);
}
The viewmodel contains a Description
property and a DueDate
property, which coincide with the properties of the TodoItem
class. When the SaveCommand
is executed, the SaveItem
method is called. SaveItem
uses the ITodoService
to persist the TodoItem
to the database, and to optionally create a live tile representing the to-do item.