Telerik blogs

{download the application complete source code from your Telerik account (register here for free if you are new to Telerik)}

One of the great new features in the new Windows Phone OS, codenamed "Mango" is that developers have access to the device appointments. By using the new APIs we can now integrate the appointments in our applications. To make the developers' lives easier we created a new Calendar control that is an exact copy of the Metro calendar found in the OS. RadCalendar is "appointment-aware" in the sense that you can create a simple appointments data source and bind the calendar to it. This way, the appointments from the data source will be displayed in the month view like in the screenshots below:

Windows Phone Calendar with appointments


With RadCalendar you can achieve the above experience out of the box. You can also specify arbitrary appointments source - for example from your web service or from a 3rd party events feed.

In this blog post I'm going to show you how to create a complete agenda viewer for Windows phone with agenda view and agenda details. The UI mimics the UI found in the Metro guidelines, so nothing to surprise you here - and ofcourse this look and feel is consistent with the one found on the device.

Here is how the agenda view looks like:

Windows Phone scheduler agenda view

To start buliding this application we need first to create the appointments source. As mentioned above the appointments source can be the device appointments or any appointments feed. To implement an appointments data source we need to inherit from the abstract Telerik.Windows.Controls.AppointmentSource class and to override the FetchData method. Here is a sample implementation of a simple appointment data source:

01.public class SampleAppointmentSource : AppointmentSource
02.    {
03.        public SampleAppointmentSource()
04.        {
05.        }
07.        public override void FetchData(DateTime startDate, DateTime endDate)
08.        {
09.            this.AllAppointments.Clear();
11.            this.AllAppointments.Add(new SampleAppointment()
12.            {
13.                StartDate = DateTime.Now,
14.                EndDate = DateTime.Now.AddHours(1),
15.                Subject = "Today Appointment 1",
16.                Details = "Some Long Details are coming here",
17.                Location = "My Home Town"
18.            });
20.            this.AllAppointments.Add(new SampleAppointment()
21.            {
22.                StartDate = DateTime.Now.AddMinutes(30),
23.                EndDate = DateTime.Now.AddHours(1),
24.                Subject = "Today Appointment 2",
26.                Details = "Some Long Details are coming here",
27.                Location = "Paris"
28.            });
30.            this.OnDataLoaded(); // notify that there is new data to display
31.        }
32.    }


Now that we have the appointments in place we can show them in RadCalendar. We need to assign it to the AppointmentSource property:

RadCalendar1.AppointmentSource = new SampleAppointmentSource();


This is all we need to do in order to display the appointments in the month view. With the help of RadCalendar this was easy. Now lets see how to create the agenda view. For this view we need to get all the appointments, to sort them by date and to group by day and time. This is not a trivial task, but with the data engine that is implemented in Telerik RadJumpList we need to just specify the correct sort and group descriptors. Here is the XAML used:

02.        <local:DayHeaderConverter x:Key="DayHeaderConverter"/>
03.        <local:TimeHeaderConverter x:Key="TimeHeaderConverter"/>
04.        <local:AppointmentToDurationConverter x:Key="AppointmentToDurationConverter"/>
05.        <local:AppointmentConflictVisibilityConverter x:Key="AppointmentConflictVisibilityConverter"/>
06.        <DataTemplate x:Key="GroupDateHeaderTemplate">
07.            <TextBlock FontSize="24" Text="{Binding Key, Converter={StaticResource DayHeaderConverter}}" Margin="0,45,0,10" />
08.        </DataTemplate>
09.        <DataTemplate x:Key="GroupTimeHeaderTemplate">
10.            <Grid Margin="0,10,0,0">
11.                <Grid.ColumnDefinitions>
12.                    <ColumnDefinition Width="*"/>
13.                    <ColumnDefinition Width="24"/>
14.                </Grid.ColumnDefinitions>
15.                <TextBlock Style="{StaticResource PhoneTextExtraLargeStyle}" Margin="0, 0, 0, -5" Text="{Binding Key, Converter={StaticResource TimeHeaderConverter}}"/>
16.                <Image HorizontalAlignment="Right" Grid.Column="1" Source="/Images/AppointmentConflict.png" Stretch="None" Visibility="{Binding Converter={StaticResource AppointmentConflictVisibilityConverter}}"/>
17.            </Grid>
18.        </DataTemplate>
19.    </phone:PhoneApplicationPage.Resources>
20.    <Grid x:Name="LayoutRoot" Margin="24,24,24,0">
21.        <Grid.RowDefinitions>
22.            <RowDefinition Height="Auto"/>
23.            <RowDefinition Height="Auto"/>
24.            <RowDefinition Height="*"/>
25.        </Grid.RowDefinitions>
26.        <TextBlock x:Name="AgendaTitle"/>
27.        <TextBlock Text="agenda" Style="{StaticResource PhoneTextTitle1Style}" Margin="0,-5,0,7" Grid.Row="1"/>
28.        <telerikDataControls:RadJumpList x:Name="RadJumpList1" IsGroupPickerEnabled="False" Grid.Row="2" ItemTap="RadJumpList1_ItemTap">
29.            <telerikDataControls:RadJumpList.ItemTemplate>
30.                <DataTemplate>
31.                    <Grid>
32.                        <Grid.ColumnDefinitions>
33.                            <ColumnDefinition />
34.                            <ColumnDefinition Width="24"/>
35.                        </Grid.ColumnDefinitions>
36.                        <Grid.RowDefinitions>
37.                            <RowDefinition/>
38.                            <RowDefinition/>
39.                        </Grid.RowDefinitions>
40.                        <TextBlock Text="{Binding Subject}" Style="{StaticResource PhoneTextAccentStyle}" Margin="0, 0, 0, -3"/>
41.                        <TextBlock Margin="0" Grid.Row="1" Text="{Binding Converter={StaticResource AppointmentToDurationConverter}}"/>
42.                        <Rectangle Fill="{StaticResource PhoneAccentBrush}" HorizontalAlignment="Center" Width="12" Height="38" Grid.RowSpan="2" Grid.Column="1"/>
43.                    </Grid>
44.                </DataTemplate>
45.            </telerikDataControls:RadJumpList.ItemTemplate>
46.        </telerikDataControls:RadJumpList>
47.    </Grid>


As you can see - it is pretty simple - we are just adding the data templates which are needed to format the appointments. Now here is the code that takes care for the actual sorting and filtering:

1.RadJumpList1.GroupHeaderTemplateSelector = new HeaderTemplateSelector() { RootGroupTemplate = (DataTemplate)this.Resources["GroupDateHeaderTemplate"], NestedGroupTemplate = (DataTemplate)this.Resources["GroupTimeHeaderTemplate"] };
2.RadJumpList1.SortDescriptors.Add(new GenericSortDescriptor<IAppointment, DateTime>(a => a.StartDate));
3.RadJumpList1.GroupDescriptors.Add(new GenericGroupDescriptor<IAppointment, DateTime>(a => a.StartDate.Date));
4.RadJumpList1.GroupDescriptors.Add(new GenericGroupDescriptor<IAppointment, DateTime>(a => a.StartDate));


Here is how the DataTemplateSelector for GroupHeaderTemplate looks like:

01.public class HeaderTemplateSelector : DataTemplateSelector
02.    {
03.        public override DataTemplate SelectTemplate(object item, DependencyObject container)
04.        {
05.            DataGroup dataGroup = item as DataGroup;
06.            if (dataGroup.HasChildGroups)
07.            {
08.                return RootGroupTemplate;
09.            }
10.            else
11.            {
12.                return NestedGroupTemplate;
13.            }
14.        }
16.        public DataTemplate RootGroupTemplate
17.        {
18.            get;
19.            set;
20.        }
22.        public DataTemplate NestedGroupTemplate
23.        {
24.            get;
25.            set;
26.        }
27.    }


Thats it! - we now have the scheduler and appointment view for Windows Phone all done. All the infrastructure and helper components for this application are now part of the Telerik Windows Phone 7 components suite. You can download the application complete source code from your Telerik account (register here for free if you are new to Telerik). You do not need the Mango bits installed in order to use the appointments, but if you want to integrate with the device appointments you need to have Mango tools installed and a Mango device in order to test.

Please let us know if you have any feedback on this application or on RadControls in general.

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 are disabled in preview mode.