Telerik blogs

Building the Home Screen Panorama

This is part 2 of the series on building WP7 ToDo application with Telerik WP7 Control toolkit. Please refer to the "master" blog post for more details about the application and links to the other part of the series.

The home screen of the application consists from the following major components:

  • Home Panorama
  • Tasks List
  • Projects List

Let’s first examine the Panorama control. The requirements were that that the logo of the application and the “New Task” button should be always visible regardless to which item of the panorama the user has scrolled. To accomplish this we are using the Title property of the Panorama control which is designed especially for this.

WP7 ToDo application - home screen title

Here is how the code looks like:

<controls:Panorama>
            <controls:Panorama.TitleTemplate>
                <DataTemplate>
                    <Grid Margin="14,90,0,0" Height="90">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Image Source="/Images/logo.png" Stretch="None" VerticalAlignment="Center" />
                        <StackPanel Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal" MouseLeftButtonDown="NewTaskButton_Click" Margin="31,0,0,0">
                            <Image Source="/Images/newTask.png" Stretch="None"/>
                            <TextBlock Text="new task" Style="{StaticResource PanoramaHeaderButtonsStyle}" FontWeight="Bold" Margin="6,-5,0,0"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </controls:Panorama.TitleTemplate>
           <controls:Panorama.Background >
               <ImageBrush ImageSource="/Images/panorama.jpg"/>
            </controls:Panorama.Background>

 

Now let’s see how the Tasks list is created. The requirement for the tasks list was that tasks should be grouped by due date, the UI should not display the exact date, but instead to have custom headers which should read: “Today”, “Tomorrow” and “Next”. This way we can highlight the most important tasks to the end users – which are ofcourse those that should be done first and leave the rest of the tasks in the “Next”group. To accomplish this we are using the Telerik JumpList control which provides this functionality almost out of the box.

Before I go into showing you the code that creates this fancy UI – please take a look at the used data model.

ToDo application data model

As you can see it is very simple – we have two major classes – Task and Project. The Task class has a lot of properties that describe the specific task and also have a ProjectId field which is pointing to the correct Project where the Task is defined. To persist the tasks and projects on the device we are using the free open source SterlingDB created by Jeremy Likness. It is very fast and provides all the needed functionality we need in our application (Detailed usage is described in this separate more advanced blog post).
 
So now that you see the data model, let’s see how to we can implement the UI shown below:

Tasks List panorama item

We are using the Telerik RadJumpList control which do basically two things:

  • Shows a list of items and provides smooth scrolling for WP7,
  • Have Group/Filter and Sort Descriptors which are very power and easy to use.

To get the list of items we are using the following database query:

TasksList.ItemsSource = (from k in SterlingService.Current.Database.Query<Task, DateTime, bool, int>("Task_DueDate_IsCompleted")
          where k.Index.Item1 >= DateTime.Today.Date
          where k.Index.Item2 == false
          orderby k.Index.Item1 ascending
          select k);

 

We are using Sterling indexes to retrieve the information – in this case we are using the "Task_DueDate_IsCompleted" index which as its name is saying is an index by DueDate and by IsCompleted property.

Now that have all the not-completed tasks sorted by DueDate it is time to configure how the JumpList will display them. We need to set the proper Sort and Group descriptors. Here is how the setup the SortDescriptor:

TasksList.SortDescriptors.Add(new GenericSortDescriptor<TableIndex<Task, Tuple<DateTime, bool>, int>, DateTime>(task => task.Index.Item1));

 

task.Index.Item1 is the DueDate of the task. We are using this syntax because we still do not want to retrieve the real data from the database. The sorting is working entirely with Database indexes.

Now let’s see how the grouping looks like:

TasksList.GroupDescriptors.Add(new GenericGroupDescriptor<TableIndex<Task, Tuple<DateTime, bool>, int>, string>(delegate(TableIndex<Task, Tuple<DateTime, bool>, int> tableIndex)
{
 if (tableIndex.Index.Item1.Date == DateTime.Now.Date)
 {
  return "TODAY";
 }
 else if (tableIndex.Index.Item1.Date == DateTime.Now.Date.AddDays(1))
 {
  return "TOMORROW";
 }
 else
 {
  return "NEXT";
 }
}));

 

XAML:

<telerikDataControls:RadJumpList GroupHeaderTemplate="{StaticResource JumpListGroupHeaderTemplate}" ItemTemplate="{StaticResource TaskDetailsTemplate}" IsAsyncBalanceEnabled="True" Margin="0" x:Name="TasksList" ItemTap="TasksList_ItemTap" CacheMode="BitmapCache"/>

              

As you can see we have again a very simple logic inside the GroupDescriptor. All that we do here is to decide in which group to include the given item. If the DueData of the item is today, we are including it in the Today group, etc.

Now that we have the data displayed the next step is to enable users to navigate to task details when tap on a task. This is done by using the ItemTap event or the RadJumpList:

private void TasksList_ItemTap(object sender, ListBoxItemTapEventArgs e)
  {
   if (TasksList.SelectedItem != null)
   {
    Task task = (TasksList.SelectedItem as TableIndex<Task, Tuple<DateTime, bool>, int>).LazyValue.Value;
    NavigationService.Navigate(new Uri("/Views/ViewTask.xaml?TaskId=" + task.Id, UriKind.Relative));
   }
  }

 

This event is raised every time when user taps on item from the JumpList, regardless if the item is selected or not.

We are now done with the first item in the Panorama. Let’s continue with the second PanoramaItem. The second item displays the list of projects, which are active. We query the database to get the list of projects with the specified properties and we display them with the RadDataBoundListBox. This time we do not use the JumpList, because we don’t need any grouping on the data.

var projectsRange = (from k in SterlingService.Current.Database.Query<Project, int, int>("Project_Status")
      where k.Index != AppModel.PROJECT_STATUS_COMPLETED_ID
      select k.LazyValue);
ProjectsList.ItemsSource = projectsRange;

 

<telerikPrimitives:RadDataBoundListBox ItemTemplate="{StaticResource ProjectDetailsTemplate}" ItemTap="ProjectsList_ItemTap" x:Name="ProjectsList" CacheMode="BitmapCache"/>

 

As you can see again – with very few lines of code we have the projects displayed. Again we are using Indexes from SterlingDB, because this is the fastest way to get only the needed info from database.

With this we are ready with the home panorama. The rest of the panorama items are just a bunch of XAML which contains links to the categories and to specific pages.

In the next blog post I’ll show you how the add/edit of tasks is done and how to use specific device capabilities like voice, map and photos.


About the Author

Valio Stoychev

Valentin Stoychev (@ValioStoychev) for long has been part of Telerik and worked on almost every UI suite that came out of Telerik. Valio now works as a Product Manager and strives to make every customer a successful customer.

 

Comments

Comments are disabled in preview mode.