DevComponents WPF Schedule Quick Start Guide

WPF Schedule control provides Outlook style scheduling functionality for your WPF 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 DevComponents.WpfSchedule.Model namespace.

Using the model we provide number of views, for example day, week or month view. The View objects can be found in DevComponents.WpfSchedule 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
_Model.Appointments.Add(appointment);

This code can be found in ScheduleControl sample project that is included with DotNetBar for WPF install. Make sure to review this project since it provided 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 create a resource key that identifies 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 Window or Application resources.

For example if you set appointment.CategoryColor = “Gold” you would need to define following resources to represent that category color:

<LinearGradientBrush x:Key="{ComponentResourceKey {x:Type s:ScheduleColors}, Appointment<strong>Gold</strong>Background}" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFFFCAA" Offset="0" />
<GradientStop Color="#FFFFF958" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="{ComponentResourceKey {x:Type s:ScheduleColors}, Appointment<strong>Gold</strong>Border}" Color="#FF7C7814" />

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. Timer markers are specific to the category color as well so category is used as part of the key to find marker resource brush.

For example if you set appointment.TimeMarkedAs = “SuperBusy” you would need to define following custom resource for this time marker:

<SolidColorBrush x:Key="{ComponentResourceKey {x:Type s:ScheduleColors}, AppointmentSuperBusyTimeMarker}" Color="Black" />

Note that you can use any other type of brush, LinearGradientBrush or DrawingBrush.

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 CalendarModel.GetDay method which returns reference to Day object with all appointments, including recurring ones on that day.

Reminders and Notifications

Appointments provide two types of notifications:

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

2.       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 Window.

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 powerful recurring appointments engine. 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
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 instancess 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;
_Model.Owners.Add(owner);

Using Views

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

CalendarView.CalendarModel = _Model;

Calendar view by default shows all 3 views Daily, Weekly and Monthly 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

You can get current view or change it using the SelectedView property.

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

End-user can navigate the view dates using date-navigator control in header of the view but you can also change each view visible date range using 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

As currently visible date range changes CalendarView.UserDateChanged event will be fired.

Since user may select the range of dates on calendar using mouse you can get or set the selected date range using DateSelectionStart and DateSelectionEnd properties.

Each view is hosted in separate tab and you can use TabHeader and TabFooter properties on CalendarView to add custom content to the header and footer of that tab control.

Appointment Images

Each appointment can have it’s own unique Image and alignment associated with it.  In order for images to be displayed in an appointment view, the project must have desired images included as resources.

Images defined in your project as resources can then be associated with a given appointment via the Appointment.ImageSource property. The Appointment.ImageSource is a string value, specifying the Name of the image resource, for example: appointment.ImageSource = “images/Calendar.png” specifies that image with name Calendar.png in folder images should be displayed on the view.

Appointment images can be aligned via the Appointment.ImageAlignment property.  It can be set to one of the following ImageContentAlignment enum values:

BottomCenter
BottomLeft
BottomRight
TopCenter
TopLeft
TopRight
LeftTop
LeftMiddle
LeftBottom
RightTop
RightMiddle
RightBottom

Here is an example of each alignment setting:

Hit Testing

If you need to know at which calendar part certain mouse coordinates point to use CalendarView.HitTest method which will return you all details you need. For example handle CalendarView.MouseDown event from XAML like this:

<s:CalendarView MouseDown="calendarView1_MouseDown">

and place this code in the event handler:

private void calendarView1_MouseDown(object sender, MouseButtonEventArgs e)
{
   Console.WriteLine(calendarView1.HitTest(e.GetPosition(calendarView1)));
}

Run the application and click on the calendar and watch VS.NET output  window to see the output of HitTest method.

Day, Week View Ruler and Time Slot Control

Day and Week views by default use the 30 minute time slot. However you can customize the time slot size by setting CalendarView.TimeSlotDuration property. Note that this value must be less or equal than 30 and grater than 1. In image below the TimeSlotDuration was set to 6 so each time slot in view is 6 minutes long.

Notice in image above that time ruler displays the time slot labels with slot time. This is specified by CalendarView.LabelTimeSlots property which has been set to true to get result you see. 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 time ruler is formatted using numeric format specified by static properties ScheduleSettings.TimeRulerHourFormatString and ScheduleSettings.TimeRulerMinuteFormatString. Each time slot Label control uses the style that is defined as such:

<Style TargetType="{x:Type Label}" x:Key="{ComponentResourceKey {x:Type s:TimeRulerHour}, TimeSlotLabel}">
<Setter Property="FontSize" Value="9" />
<Setter Property="Foreground" Value="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=s:ScheduleColors, ResourceId={x:Static s:ScheduleColors.HourRulerForeground}}}" />
</Style>

Selection in Views

Appointment model objects are represented in views using instances of AppointmentView object. Each AppointmentView object will raise the Selector.SelectedEvent or Selector.UnselectedEvent events as their selection status changes in User Interface.

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 or not.

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 end-user can move, resize (change duration) and change the owner of the appointments. To detect these changes following bubbling events on AppointmentView are provided:

  • AppointmentView.BeforeAppointmentDragEvent – Occurs before the drag & drop or resize operation by end-user is initiated. You can cancel the operation if desired by setting Cancel property on its event arguments, CancelableRoutedEventArgs.Cancel=true
  • AppointmentView.AppointmentChangingEvent – Occurs during the drag & drop or resize operation and gives you information about nature of the change (move, resize, change owner) as well as opportunity to get access to new start/end time for the appointment and it allows you to cancel the change by setting Cancel=true on its event arguments.
  • AppointmentView.AppointmentChangedEvent – Occurs after drag & drop or resize operation is completed and gives you information about the nature of the change.

In XAML you can handle these appointments on CalendarView top-level control like so:

<s:CalendarView
            s:AppointmentView.BeforeAppointmentDrag="CalendarView_BeforeAppointmentDrag"
            s:AppointmentView.AppointmentChanging="CalendarView_AppointmentChanging"
            s:AppointmentView.AppointmentChanged="CalendarView_AppointmentChanged"

In code you can attach your event handlers to CalendarView as shown here:

MyCalendarView.AddHandler(DevComponents.WpfSchedule.AppointmentView.BeforeAppointmentDragEvent,
    new RoutedEventHandler(OnBeforeAppointmentDrag));
MyCalendarView.AddHandler(DevComponents.WpfSchedule.AppointmentView.AppointmentChangingEvent,
    new RoutedEventHandler(OnAppointmentChanging));
MyCalendarView.AddHandler(DevComponents.WpfSchedule.AppointmentView.AppointmentChangedEvent,
    new RoutedEventHandler(OnAppointmentChanged));
 
private void OnAppointmentChanged(object sender, RoutedEventArgs e)
{
  DevComponents.WpfSchedule.AppointmentChangedRoutedEventArgs args =
    (DevComponents.WpfSchedule.AppointmentChangedRoutedEventArgs)e;
  Console.WriteLine("{0}  Appointment Changed action={1}", DateTime.Now, args.ChangeType);
}
private void OnAppointmentChanging(object sender, RoutedEventArgs e)
{
  DevComponents.WpfSchedule.AppointmentChangingRoutedEventArgs args =
    (DevComponents.WpfSchedule.AppointmentChangingRoutedEventArgs)e;
  Console.WriteLine("{0}  Appointment Drag action={1}", DateTime.Now, args.ChangeType);
}
private void OnBeforeAppointmentDrag(object sender, RoutedEventArgs e)
{
  DevComponents.WpfSchedule.CancelableRoutedEventArgs args =
    (DevComponents.WpfSchedule.CancelableRoutedEventArgs)e;
  Console.WriteLine("{0}  Before Appointment Drag", DateTime.Now);
}

Finding Appointment View

Using  GetAppointmentView method you can retrieve the AppointmentView for given Appointment in currently selected calendar view.

The default CalendarView implementation provides a sample Reminder Dialog which should be used as starting point for creation of your own reminder dialog. AutoPopupReminderDialog property indicates whether the internal reminder dialog is used to display appointment reminders.

Adding Custom Elements to Calendar View

CalendarView supports adding of any WPF Visual that inherits from UIElement to its views and it will automatically position and resize the element on the calendar based on the attached properties you set on the element to indicate its position on time-line. 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. Note that both start and end time must be set. 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. Note that both start and end time must be set. . From code you use static methods CalendarView.GetEndTime and CalendarView.SetEndTime to get or set the end time for an element.
  • CalendarView.IsAllDayEvent – Gets whether custom element is considered to be all day event. This is read-only property that is automatically managed by the control and it depends on StartTime and EndTime property settings. From code you use static method CalendarView.GetIsAllDayEvent to get whether an element is considered to be all day event.
  • CalendarView.ParentView – Gets the parent view that element is currently displayed on. Custom elements can be displayed only on single view at a time. This read-only property provides you with the information on which view the element is displayed so you can adjust it if necessary.  From code you use static method CalendarView.GetParentView to get the calendar view element is displayed on.

Here is sample XAML that shows one way to add custom elements to calendar views:

<s:CalendarView Grid.Row="1" LicenseKey="DAD80300DA22">
<!-- This is how to add any WPF UIElement based content to calendar -->
<Border realsrc="Yellow"  background="http://www.devcomponents.com/kb/admin/Yellow"  BorderBrush="Red" BorderThickness="1" s:CalendarView.StartTime="2/1/2009  10:00 AM" s:CalendarView.EndTime="2/1/2009 11:00 AM">
<TextBlock Text="Custom Content" TextBlock.TextTrimming="CharacterEllipsis" />
</Border>
</s:CalendarView>

C# code:

Border customElement = new Border();
customElement.Background = Brushes.Red;
customElement.BorderBrush = Brushes.Black;
customElement.BorderThickness = new Thickness(1d);
DevComponents.WpfSchedule.CalendarView.SetStartTime(customElement, DateTime.Today.AddHours(8));
DevComponents.WpfSchedule.CalendarView.SetEndTime(customElement, DateTime.Today.AddHours(10));
DevComponents.WpfSchedule.CalendarView.SetOwnerKey(customElement, "PBS");
calendarView1.Items.Add(customElement);

VB code:

Dim customElement As New Border()
customElement.Background = Brushes.Red
customElement.BorderBrush = Brushes.Black
customElement.BorderThickness = New Thickness(1R)
DevComponents.WpfSchedule.CalendarView.SetStartTime(customElement, DateTime.Today.AddHours(8))
DevComponents.WpfSchedule.CalendarView.SetEndTime(customElement, DateTime.Today.AddHours(10))
DevComponents.WpfSchedule.CalendarView.SetOwnerKey(customElement, "PBS")
calendarView1.Items.Add(customElement)

Important: When adding custom controls to Schedule you must make sure that Width and Height on such controls is not set. If you create them in VS.NET make sure that you remove Width and Height settings. Each calendar view must be able to determine the Width and Height of the control.

Changing Color Scheme and Customizing Colors

In default configuration, WPF Schedule control includes Office 2007 style with the Blue, Black and Silver color schemes. The scheme is changed using single line of code. For example to change the color scheme to Office 2007 Black scheme you would use following code:

DevComponents.WpfSchedule.ScheduleColors.ChangeColorScheme(DevComponents.WpfSchedule.eScheduleVisualStyle.Office2007Black);

Every color used by the calendar controls can be customized by defining the brush resources as either part of the control, if color changes are per control instance, or as part of Window resource dictionary if color changes are per window. You can also define resources in Application resources if you want these customization to be application wide.

The keys for the resources used by calendar controls are defined as static members of the ScheduleColors class. For example following is the resource defined for the calendar Day view working hours background:

<SolidColorBrush x:Key="{ComponentResourceKey {x:Type s:<span style="background-color: #ffff99;">ScheduleColors</span>}, {x:Static s:<span style="background-color: #ccffff;">ScheduleColors.DayWorkHoursBackground</span>}}" Color="#FFFFFFFF" />

In the XAML above notice two things:

  1. The type used in ComponentResourceKey is always ScheduleColors
  2. The key used in ComponentResourceKey is defined as static member of ScheduleColors class.

Using the same key you can define new brush to be used for the working hours background in day view. Notice that instead of solid color brush you can use any other brush, in this example linear gradient brush. Here are examples:

Defining resources on Control level would apply only to that control instance:

<s:CalendarView>
<s:CalendarView.Resources>
<LinearGradientBrush  x:Key="{ComponentResourceKey {x:Type s:ScheduleColors}, {x:Static  s:ScheduleColors.DayWorkHoursBackground}}" StartPoint="0,0"  EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Yellow" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</s:CalendarView.Resources>
</s:CalendarView>

Defining resources on Window level would apply to all controls on the same window:

<Window>
<Window.Resources>
<LinearGradientBrush  x:Key="{ComponentResourceKey {x:Type s:ScheduleColors}, {x:Static  s:ScheduleColors.DayWorkHoursBackground}}" StartPoint="0,0"  EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Yellow" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Window.Resources>

Changing Time Slot Colors

You can customize time slot background and pen colors on day/week view for specific dates and specific days. You can use this to mark certain times on the calendar. Following screen-shot shows such customization applied:

Notice the background color changes behind actual appointments. This is accomplished using following code:

// Mark time slots in Day/Week view for today
MyCalendarView.ViewDisplayCustomizations.DaySlotBackgrounds.Add(DateTime.Today,
new DaySlotAppearance(10, 0, 15, 0, Brushes.PeachPuff, new Pen(Brushes.Plum, 1d)));
MyCalendarView.ViewDisplayCustomizations.DaySlotBackgrounds.Add(DateTime.Today,
new DaySlotAppearance(20, 0, 23, 0, Brushes.SpringGreen));
// You can also mark slots per day like this
MyCalendarView.ViewDisplayCustomizations.DaySlotBackgrounds.Add(DayOfWeek.Friday,
new DaySlotAppearance(8, 0, 9, 0, Brushes.SandyBrown));

To remove customizations you can use following code:

// Remove all time-slot markers for today
MyCalendarView.ViewDisplayCustomizations.DaySlotBackgrounds.Remove(DateTime.Today);
// And per-day markings
MyCalendarView.ViewDisplayCustomizations.DaySlotBackgrounds.Remove(DayOfWeek.Friday);

When calendar is displaying multiple owners/users you can also specify the time-slot customizations per-owner like so:

DevComponents.WpfSchedule.DaySlotAppearances appearances = new DevComponents.WpfSchedule.DaySlotAppearances();
// Specific dates
appearances.Add(new DateTime(2012, 6, 1),
new DaySlotAppearance(6, 0, 10, 0, Brushes.PeachPuff, new Pen(Brushes.Red, 1d)));
appearances.Add(new DateTime(2010, 12, 7),
new DaySlotAppearance(1, 0, 4, 0, Brushes.GreenYellow));
// For day of week
appearances.Add(DayOfWeek.Saturday,
new DaySlotAppearance(20, 0, 24, 0, Brushes.Indigo));
// Add customizations
CalendarView.ViewDisplayCustomizations.OwnerDaySlotBackgrounds.Add("OwnerKeyHere", appearances);

Localization of system text

Schedule control uses some system text on its UI which is by default in English language. To localize system text you need to define your own text resource and include it as part of your Window.Resources or Application.Resources. Here is default resource that schedule control uses:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:s="clr-namespace:DevComponents.WpfSchedule"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.TimelineNavigationPreviousPage}}">Previous timeline page</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.TimelineNavigationTodayPage}}">Todays timeline page</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.TimelineNavigationNextPage}}">Next timeline page</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.AppointmentCalloutNotes}}">notes</sys:String>
 
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.DayTabHeader}}">Day</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.WeekTabHeader}}">Week</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.MonthTabHeader}}">Month</sys:String>
    <sys:String x:Key="{ComponentResourceKey {x:Type s:StringKeys},
      {x:Static s:StringKeys.TimelineTabHeader}}">Timeline</sys:String>
</ResourceDictionary>

Control also uses the current system culture to get day names, formatting rules for dates etc. If you want to let control use different culture you can set static property ScheduleSettings.CurrentCulture like so:

CultureInfo culture = new CultureInfo(cultureName);
DevComponents.WpfSchedule.ScheduleSettings.CurrentCulture = culture;
CalendarView.UpdateCultureText();




ICS (Internet Calendaring and Scheduling – RFC5545) Support

Model Appointments can be Imported from, and Exported to, industry standard ICS files.

Importing:

In order to import from an existing ICS file, you will need to allocate an ICS Import object and initialize it to suit your requirements. The following code will attempt to open the file “HolidaySchedule.ics” and import all ICS “Event” and “Alarm” components (VEVENT and VALARM) into the associated CalendarModel:

// Allocate and initialize our importer object
IcsImporter ics = new IcsImporter(_CalendarView.CalendarModel);
ics.IncludeComponent = IcsImporter.IcsComponent.Event | IcsImporter.IcsComponent.Alarm;
// Perform the actual import into our CalendarModel
ics.Import("HolidaySchedule.ics");

Each ICS file can contain multiple “Calendar” components (VCALENDAR). Each ICS encountered Calendar entry has a given name. The following is an example of an ICS file that contains 2 Calendar entries, whose calendar names (X-WR-CALNAME) are “Salaried” and NonSalaried”:

BEGIN:VCALENDAR
PRODID:-//DotNetBar\, Inc//iCal 1.0//EN
VERSION:2.0

CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Salaried
BEGIN:VEVENT
DTSTAMP:20020917T175455Z
UID:1574C48A-74F0-11D7-9029-000A2789940A
SUMMARY:New Year's Day
RRULE:FREQ=YEARLY;BYMONTH=1
DTSTART;VALUE=DATE:20020101
DTEND;VALUE=DATE:20020102
END:VEVENT
END:VCALENDAR

BEGIN:VCALENDAR
PRODID:-//DotNetBar\, Inc//iCal 1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:NonSalaried
BEGIN:VEVENT
DTSTAMP:20020917T175456Z
UID:1574E702-74F0-11D7-9029-000A2789940A
SUMMARY:Remembrance Day
RRULE:FREQ=YEARLY;BYMONTH=11
DTSTART;VALUE=DATE:20021111
DTEND;VALUE=DATE:20021112
END:VEVENT
END:VCALENDAR

By default, the ICS file specified Calendar names (X-WR-CALNAMEs) are used to specify the Appointment OwnerKey when adding new appointments generated via the processing of VCalendar event components (VEVENTS, VTODO, VALARM, etc). So, for example, letting the ICS importer perform the import with it’s default import specification, you will get the foillowing results (given the above sample ICS file contents):

        ics.Import("HolidaySchedule.ics"):

Appointment #1:

   OwnerKey = "Salaried";
   StartDate = 01/01/2002
   EndDate = 01/02/2002

Subject = “New Year’s Day”

Appointment #2:

   OwnerKey = "NonSalaried";
   StartDate = 11/11/2002
   EndDate = 01/02/2002

    Subject = "New Year's Day"

If you only want to import a single Calendar component from the given ICS file (for example, the “NonSalaried” Calendar component in our above case), you can do the following:

ics.Import("HolidaySchedule.ics", "NonSalaried");

If a provided Calendar Name is set to null or the null string, then all imported appointments will be added with the OwnerKey set to “”.

You can also designate that a given ICS file calendar entry is to be associated with a given Appointment OwnerKey. So, for instance, if you wanted to have the above “Salaried” calendar entries added as appointemts, with each appointment’s OwnerKet set to “Richard”, you could do the following:

ics.Import("HolidaySchedule.ics", "Salaried", "Richard");

If you want to remap several Calendar entries into associated OwnerKey values, you can do the following:

string[] calNames = new {"Salaried", "NonSalaried"};
string[] ownerKeys = new {"Bob", "Sally"};
 
ics.Import("HolidaySchedule.ics", calNames, ownerKeys);

The above array parameters specify a one-to-one mapping between ICS Calendar Names and Appointment OwnerKeys. All “Salaried” Calendar added appointments will have their OwnerKey set to “Bob”, and all “NonSalaried” Calendar added appointments will have their OwnerKey set to “Sally”.

If, when calendar names are specified, the ICS importer encounters Calendar Names not contained in the provided list, then they will be bypassed and no appointments will be generated from them.

If a specified Calendar Name does not have a corresponding OwnerKey entry, then all imported appointments for the specified Calendar will be added with the associated OwnerKey set to the name of the Calendar.

Exporting:

In order to export to an ICS file, you will need to allocate an ICS Export object and initialize it to suit your requirements. The following code will export all CalendarModel appointments to the file “MySchedule.ics”:

// Allocate and initialize our exporter object
IcsExporter ics= new IcsExporter(_CalendarView.CalendarModel);
 
// Perform the actual export of our CalendarModel Appointments
ics.Export("MySchedule.ics");

If you want to only export appointments with a specific OwnerKey (for example, “Charlie”), you can do the following:

ics.Export("MySchedule.ics", "Charlie");

You can also export all appointments for a given OwnerKey, and specify what it’s given CalendarName should be. For example, the following code will export all appointments with OwnerKey equal to “Charlie” and name the resultant calendar “Salaried”:

ics.Export("MySchedule.ics", "Charlie", "Salaried");

As with imported ICS files, exported ICS files can also contain multiple “Calendar” components (VCALENDAR), with each Appointment OwnerKey being associated with a given Calendar entry. The following is an example where Appointments whose OwnerKey is “Sue” will be exported as CalendarName “Salaried”, and appointments with OwnerKey “Benton” will be exported as CalendarName “NonSalaried” :

string[] ownerKeys = new {"Sue", "Benton"};
string[] calNames = new {"Salaried", "NonSalaried"};
 
ics.Export("MySchedule.ics", ownerKeys, calNames);

Related posts:

  1. How to change width or height of WPF Calendar/Schedule control scroll-bars
  2. How to Assign Context Menu to Appointment View
  3. How to enumerate all Appointments between two dates in Schedule control
  4. How to set custom Style for Appointment Views
  5. ToggleSwitch Quick Start Guide