Silverlight Schedule control provides Outlook style scheduling functionality for your Silverlight applications.

Schedule control is built on Model/View paradigm. The model represents the actual schedule, i.e. appointments and recurrence. The model objects can be found in the DevComponents.Silverlight.Schedule.Model namespace. The model used in the Silverlight version of Schedule is the same as the model used in both the WPF and the WinForms versions of Schedule.

Using the model we provide a number of views, for example day, week, month or timeline view. The View objects can be found in DevComponents.Silverlight.Schedule namespace.

This provides clear separation between UI and data and allows us to present same data in number of different views even if the views are visible at the same time and present exact same underlining data.

Creating Model and Appointments

Usually you would have one Calendar model in your application that you work with. You would for example store it as member variable of your main Window and you would use it to add new appointments, remove them, etc.

Here is an example of how to create Calendar model with one appointment:

CalendarModel _Model = new CalendarModel();
// Create new appointment and add it to the model
// Appointment will show up in all views attached to model automatically
Appointment appointment = new Appointment();
appointment.Subject = "Create Demo Application";
appointment.StartTime = DateTime.Now;
appointment.EndTime = appointment.StartTime.AddMinutes(45);
appointment.CategoryColor = Appointment.CategoryGreen;
appointment.TimeMarkedAs = Appointment.TimerMarkerBusy;
// Add appointment to the model

Similar code can be found in the Schedule control sample project that is included with DotNetBar for Silverlight install. Make sure to review this project since it provides a great reference on how to use the control.

Appointment Category Colors


Note how appointment Category Color is specified through the CategoryColor property. CategoryColor is string type which is used to select resource keys that identify the Appointment view background and border brushes. We provide the default colors through static members on Appointment class like Appointment.CategoryGreen, Appointment.CategoryYellow etc. You can also define custom category colors in your Application resources.

For example if you set appointment.CategoryColor = “Gold” you would need to define following brushes in Application.Current.Resources to represent that category color:

&lt;LinearGradientBrush x:Key="Appointment<b>Gold</b>Background" StartPoint="0,0" EndPoint="0,1"&gt;
    &lt;GradientStop Color="#FFFFFCAA" Offset="0" /&gt;
    &lt;GradientStop Color="#FFFFF958" Offset="1" /&gt;&lt;
&lt;SolidColorBrush x:Key="Appointment<b>Gold</b>Border" Color="#FF7C7814" /&gt;

Note the highlighted “Gold” custom keyword that you used as CategoryColor property value.

You can also set CategoryColor to ARGB hexadecimal color that you want to use as appointment background. For example setting:

app.CategoryColor = "#FFFF0000";

will render appointment with red background.

Appointment Time Markers

Same principal applies to Appointment time marker. The time-marker is the small vertical strip on the left hand side of appointment as shown in image below:


When you set TimeMarkedAs property the value you assign is used as part of the key to find the resources brush for the marker. For example, if you set appointment.TimeMarkedAs = “SuperBusy” you would need to define following brush in Application.Current.Resources for this time marker:

&lt;SolidColorBrush x:Key="AppointmentSuperBusyTimeMarker" Color="Black" /&gt;

Note that you can use any other type of brush supported in Silverlight, not just a SolidColorBrush.

You can also set TimeMarkedAs to ARGB hexadecimal color that you want to use as appointment background. For example setting:

app.TimeMarkedAs = "#FF00FF00";

will render appointment time marker with green background.

Working with Appointments

Appointments are stored in CalendarModel.Appointments collection. However, if you are using recurring appointments then only original appointment instance will be found in Appointment collection. To get all appointments on certain day you would use method CalendarModel.GetDay which returns reference to Day object with all appointments, including recurring ones on that day.

Reminders and Notifications

Appointments provide two types of notifications:

Start Time reached notification through Appointment.StartTimeReached and CalendarModel. AppointmentStartTimeReached events. You must set Appointment.StartTimeAction= StartTimeReachedEvent for this event to occur.

Reminders added to appointment’s Reminders collection. CalendarModel.ReminderNotification event is fired when reminder time has been reached. For example to create appointment with reminder in 2 minutes from now you would do following:

appointment.Reminders.Add(new Reminder(DateTime.Now.AddMinutes(2)));

Worth noting on notifications is that each notification is being fired from background thread. That means that if you plan to interact with the User Interface you must marshal the calls from notification event handler so they execute on the UI thread. You would use: this.Dispatcher.BeginInvoke method to do so inside of your Silverlight application.

Once reminder is triggered you can snooze it using Reminder.Snooze method.

CalendarView used to provide calendar views already provides you with the AppointmentReminder event which does all work for you. Marshaling calls is only necessary if you handle notifications directly on CalendarModel or Appointment.

Recurring Appointments

WPF Schedule control provides a powerful recurring appointments engine. The following recurrence types are supported:

  • Daily for appointments that recur every day
  • Weekly for appointments that recur weekly or on certain days of week
  • Monthly for appointments that recur every month
  • Yearly for appointments that recur yearly

To set appointment recurrence you first need to set Appointment.Recurrence.RecurrenceType to the recurrence pattern you want to use i.e. Daily, Weekly, Monthly or Yearly. Then you set recurrence pattern properties through corresponding property i.e.:

  • Daily recurrence use: Appointment.Recurrence.Daily
  • Weekly recurrence use: Appointment.Recurrence.Weekly
  • Monthly recurrence use: Appointment.Recurrence.Monthly
  • Yearly recurrence use: Appointment.Recurrence.Yearly

For example to create daily appointment recurrence that repeats appointment every 3rd day and ends in 30 days you would set properties as follow:

// Set recurrence type to daily
appointment.Recurrence.RecurrenceType = eRecurrencePatternType.Daily;
// Recurrence properties are changed then on respective object Daily, Weekly, Monthly, Yearly
appointment.Recurrence.Daily.RepeatOnDaysOfWeek = eDailyRecurrenceRepeat.All;
// Repeate every 3 days&lt;
appointment.Recurrence.Daily.RepeatInterval = 3;
// End recurrence 30 days from today
appointment.Recurrence.RangeEndDate = DateTime.Today.AddDays(30);

To create an appointment that repeats on last Friday every month you would set properties as follows:

appointment.Recurrence.RecurrenceType = eRecurrencePatternType.Monthly;
appointment.Recurrence.Monthly.RelativeDayOfWeek = DayOfWeek.Friday;
appointment.Recurrence.Monthly.RepeatOnRelativeDayInMonth = eRelativeDayInMonth.Last;

If you want to remove single or multiple recurring appointments from the series you can add the date you want recurring appointment not generated to appointment.Recurrence.SkippedRecurrences collection.
Recurring appointments inherit the Visible property from its root appointment meaning that if root appointment is hidden the recurring appointments will be hidden as well. In case that you want to hide root appointment but keep recurring appointments visible and control their visibility by yourself, set appointment.Recurrence.IndependentVisibility=true.

Changing Working Hours

Day and week views render working hours and working days in different color to indicates working hours in calendar view. To change working hours you would modify members of CalendarModel.WorkDays collection. The WorkDays collection contains instances of WorkDay objects that describe single working day. By default you will find 5 instances of WorkDay object in CalendarModel.WorkDays collection: Monday, Tuesday, Wednesday, Thursday and Friday. To change working hours you would access the day you want to change working hours and set new working time. Here is sample code to do that for Monday:

WorkDay workDay = _Model.WorkDays[DayOfWeek.Monday];
WorkTime workStartTime = new WorkTime();
workStartTime.Hour = 10;
workStartTime.Minute = 30;
workDay.WorkStartTime = workStartTime;
// Set working day end time
WorkTime workEndTime = new WorkTime();
workEndTime.Hour = 20; // 8:00 PM, 24 hour format is used
workEndTime.Minute = 0;
workDay.WorkEndTime = workEndTime;

Note that you can also set the working hours per calendar resource/user. Here is code that sets working hours for resource “John” to be on Saturday and Sunday from 5:00 – 12:00:

Owner owner = new Owner("John");
owner.WorkDays.Add(new WorkDay(DayOfWeek.Saturday, new WorkTime(5, 00), new WorkTime(12, 00)));
owner.WorkDays.Add(new WorkDay(DayOfWeek.Sunday, new WorkTime(5, 00), new WorkTime(12, 00)));
owner.ColorScheme = eOwnerColor.Yellow;

Using Views

To view CalendarModel  we provide CalendarView control which shows Day, Week, Month and Timeline view for given model. All that is needed to get started is to connect a model to a view using the following statement:

CalendarView.CalendarModel = new CalendarModel();

Calendar view by default shows all 4 views: Daily, Weekly, Monthly and Timeline, but this can be controlled using following properties that show/hide individual views:

  • DayViewVisibility for day view visibility
  • WeekViewVisibility for weekly view visibility
  • MonthViewVisibility for month view visibility
  • TimelineViewVisibility for timeline view visibility

You can get current view or change it using the SelectedViewType property, which returns an enumeration indicating the current view.

To hide the tab-strip that displays the available views for user selection (Day, Week, Month, Timeline) you can use TabStripVisibility property. You simply set it to TabStripVisibility="Collapsed"

End-user can navigate the view dates using the date navigator in the header of the view but you can also change each view’s visible date range using the following properties:

  • DayViewDate to get/set current date in Day view
  • WeekViewStartDate, WeekViewEndDate to get/set the date range visible in Week view
  • MonthViewStartDate, MonthViewEndDate to get/set the date range visible in Month view
  • TimelineViewStartDate, TimelineViewEndDate to get/set the date range visible in Timeline view.

Since the user may select a range of dates on the calendar using the mouse you can get the selected date range using DateSelectionStart and DateSelectionEnd properties. This applies to all 4 views.

The 4 views are hosted in a tab control and you can use TabHeader and TabFooter properties on CalendarView to add custom content to the header and footer of that tab control.

Hit Testing

If you need to know what part of the calendar certain mouse coordinates point to use CalendarView.HitTest method which will return all the details you need. For example, handle the MouseLeftButtonDown event for the in your application’s code using AddHandler, like this:

AddHandler(FrameworkElement.MouseLeftButtonDownEvent,new MouseButtonEventHandler(HandleMouseLeftButtonDown), true);

and here is the event handler:

private void HandleMouseMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    CalendarHitTestResult hitTestResult = Calendar.HitTest(e.GetPosition(Calendar));

Examine the instance of CalendarHitTestResult for information about where the mouse click occurred in relation to visible elements of the calendar control.

Day and Week View Time Ruler and Time Slots

The Day and Week views by default use a 30 minute time slot. However you can customize the time slot duration by setting CalendarView.TimeSlotDuration property. Note that to be valid, this value should be a multiple of 60. In image below TimeSlotDuration was set to 6 so each time slot is 6 minutes long.


Notice in image above that the time ruler displays the time slot labels with the slot’s time. This is optional and can be turned off by setting CalendarView.LabelTimeSlots property to false. The Time Ruler uses 24 hour (military) time format by default. To switch to AM/PM use CalendarView.Is24HourFormat property. Each hour and minute value displayed in the time ruler is formatted using numeric format string specified by the static values ScheduleSettings.TimeRulerHourFormatString and ScheduleSettings.TimeRulerMinuteFormatString.

Selection in Views

Appointment model objects are represented in views using instances of controls deriving from AppointmentView object. Each AppointmentView object will raise the AppointmentView.IsSelectedChanged event as their selection status changes in the user Interface. Note that this event is a DevComponents Routed Event with a routing strategy of Bubble.

CalendarView.SelectedAppointments property returns the read-only collection of all selected AppointmentView objects in current view.

You can use AppointmentView.IsSelected property to get or set whether an appointment view is selected.

To prevent an appointment from being selected by end-user in view and its time changed set Appointment.Locked = true.

Detecting User Changes

By default the end-user can move (change start time/end time) and resize (change duration) appointments. To detect these changes the following routed events on AppointmentView are provided:

  • AppointmentView.DragStarted – Occurs when the move or resize operation by end-user is initiated. You can cancel the operation if desired by setting Cancel property on its event arguments to true.
  • AppointmentView.DragComplete – Occurs after drag or resize operation is completed.

Note that both of these events are implemented as DevComponents Routed Events. To handle event DragStarted, use the AddHandler extension method (defined in DevComponents.Silverlight.Controls.Eventing namespace) as such:

this.AddHandler(AppointmentView.DragStartedEvent, new RoutedEventHandlerEx(HandleAppointmentDragStarted));

private void HandleAppointmentDragStarted(object sender, RoutedEventArgsEx e)
    // Prevent appointment from being dragged.
    e.Handled = true;

Appointment Reminder Dialog

A default dialog window is shown for appointment reminders. To prevent the default dialog from being shown for all reminders, set CalendarView.AutoPopupReminderDialog property to false. To prevent the dialog from being shown for individual appointments, set up a handler for the CalendarView.AppointmentReminder routed event and set the event argument’s Handled property to true.

The default reminder dialog window is an instance of System.Windows.Controls.ChildWindow which has had it’s Content property set to an instance of DevComponents.Silverlight.Schedule.ReminderWindowViewModel and its ContentTemplate property set to a resource with the key “AppointmentReminderContentTemplate” that is located in Application.Resources. This template can be overridden with a template of your own design.

Adding Custom Elements to Calendar View

CalendarView supports adding of any UIElement to its views and it will automatically position and size the element on the calendar based on the attached properties you set. Since CalendarView inherits from ItemsControl you simply add your custom elements to CalendarView.Items collection. Then using CalendarView attached properties you position the element on calendar.

Following attached properties are provided to aid placing custom content on views:

  • CalendarView.StartTime – Gets or sets the start time for the custom element. From code you use static methods CalendarView.GetStartTime and CalendarView.SetStartTime to get or set the start time for an element.
  • CalendarView.EndTime – Gets or sets the end time for the custom element. From code you use static methods CalendarView.GetEndTime and CalendarView.SetEndTime to get or set the end time for an element.
  • CalendarView.OwnerKey – Optional value which determines the owner of the object.

There are examples of custom elements in both of the sample applications which are included in the Schedule release.  Here is sample XAML that shows one way to add custom elements to calendar views:

&lt;Border schedule:CalendarView.StartTime="9/12/2010 10:00 AM" 
        Background="Orange" BorderBrush="Red" BorderThickness="1"&gt;
    &lt;TextBlock Text="Multiple day custom object owned by Jeff" /&gt;

Here is the same thing in C# code:

Border border = new Border
    Background = new SolidColorBrush(Colors.Orange),
    BorderBrush = new SolidColorBrush(Colors.Red),
    BorderThickness = new Thickness(1),
    Child = new TextBlock { Text = "Multiple day custom object owned by Jeff" }
CalendarView.SetStartTime(border, DateTime.Now.Date.AddDays(-4).AddHours(11));
CalendarView.SetEndTime(border, DateTime.Now.Date.AddDays(4).AddHours(20));
CalendarView.SetOwnerKey(border, "jeff");

Note: Each calendar view determines the width and height of a custom UI Element based on the values you supply for start and end time. Do not set values for Width and Height on a UIElement when making it a custom item of the CalendarView control.

Further Customization

Changing Color Scheme and Customizing Colors

In the default configuration, Silverlight Schedule control includes Office 2010 blue and silver color schemes and Office 2007 blue, black and silver color schemes.

The active color theme can be set and/or modified by following the same procedure as for all DotNetBar for Silverlight controls.

Customizing Appointment Views

Appointment views are fully customizable. For complete instructions, see this KB article.

Customizing Day and Week View Time Slots

The day and week view time slots can be customized on a per day/per time range basis. For complete details, see this KB article.

Customizing Days in Month View

The individual days in Month view can be customized, both their headers and their content. For complete details, see this KB article.

ContextMenu Support

Support for context menu is extended in the Schedule controls via the routed event CalendarView.ContextMenuOpening which is raised when any DevComponents.Silverlight.Controls.ContextMenu is about to open from within it. The event arguments include the hit test results from a call to method CalendarView.HitTest. The event provides an opportunity to modify, add or remove context menu items depending on the hit test results. To keep the context menu from opening, set the event argument’s Handled property to true.

Related posts:

  1. Silverlight Schedule Control Quick Start Guide
  2. How to enumerate all Appointments between two dates in Schedule control
  3. Customizing Time Slots in Silverlight Schedule
  4. How to display the number of appointments for a day in month view of Silverlight Schedule.
  5. Customizing Appointment Views in Silverlight Schedule