windowsforms-120605-controls-and-libraries-scheduler-import-and-export-google-calendars.md
DevExpress Scheduler can synchronize its regular, recurring and all-day Appointments (in Google terminology, “Events”) with Google Calendars. The synchronization process works in a two-way mode: you cannot only import or export data to the control/Google calendar.
The Scheduler control uses the DXGoogleCalendarSync component to transfer data between a Google calendar and a control storage (both SchedulerDataStorage and its predecessor SchedulerStorage are supported).
This tutorial builds a sample WinForms application that exchanges Appointments/Events between an unbound SchedulerControl and Google calendars.
To browse complete sample code and download the Visual Studio project, visit the How To: Synchronize Scheduler Control Appointments with Google Calendar Events GitHub example.
Start a new Visual Studio project based on the “Scheduling Application” project template.
Create a new Ribbon group and add a regular push button (BarButtonItem) and an edit item (BarEditItem) with the RepositoryItemComboBox editor within.
Change the button name to “bbiSynchronize” and RepositoryItem name to “ricbCalendarList” to avoid errors when you copy-and-paste code snippets from this article.
Install the following dependency library (NuGet package): Google.Apis.Calendar.v3 1.35.1.1321+
Invoke the SchedulerControl’s smart-tag menu and click Sync with Google Calendar.
Open the Google Calendar API .NET Quickstart documentation article and follow steps 1 to 3b to acquire the “credentials.json” file and include it into your project.
Override the OnLoad method to specify the DXGoogleCalendarSync component’s DXGoogleCalendarSync.CalendarService property and log into Google services using the credentials file you downloaded.
Add the following code to extract the calendar list and populate the combo box editor in the Ribbon with corresponding items. The “UpdateBbiAvailability” method disables the “Sync” button if there is no selected calendar.
When the combo box shows available calendars, you can handle the item selection, retrieve the selected calendar’s ID and pass it to the component DXGoogleCalendarSync.CalendarId property.
To start synchronization, call the DXGoogleCalendarSync.Synchronize method.
Specify the DXGoogleCalendarSync.Storage property to bind Google Calendar to a SchedulerDataStorage or SchedulerStorage object.
The sample application is now ready. At first launch, it will ask you to sign in with any Google account (this does not have to be the same account you used to download the “credentials.json” file).
All Google Events have two properties that establish Event identities:
The DXGoogleCalendarSync component automatically adds two Appointment custom fields (the IPersistentObject.CustomFields collection) to store these identifiers: “gID” and “etag”. You can use the DXGoogleCalendarSync.CustomFieldIdPropertyName and DXGoogleCalendarSync.CustomFieldETagPropertyName component properties to change these default custom field names.
If you want to store ID and ETag values in a data source bound to your storage, add corresponding custom field mappings.
schedulerStorage.Appointments.CustomFieldMappings.Add(new AppointmentCustomFieldMapping("gId", "database_ID_field_name"));
schedulerStorage.Appointments.CustomFieldMappings.Add(new AppointmentCustomFieldMapping("etag", "database_ETag_field_name"));
schedulerStorage.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("gId", "database_ID_field_name"))
schedulerStorage.Appointments.CustomFieldMappings.Add(New AppointmentCustomFieldMapping("etag", "database_ETag_field_name"))
If for specific Scheduler Appointments no matching Google Calendar Events should be created (or vice versa), handle the DXGoogleCalendarSync.FilterAppointments event.
The sample below skips all appointments that have “test” in their descriptions, and all Google Events with the “tentative” status.
private void GcSyncComponent_FilterAppointments(object sender, FilterAppointmentsEventArgs e) {
if (e.Appointment!=null && e.Appointment.Description.Contains("test"))
e.Cancel = true;
if (e.Event!=null && e.Event.Status == "tentative")
e.Cancel = true;
}
Private Sub GcSyncComponent_FilterAppointments(ByVal sender As Object, ByVal e As FilterAppointmentsEventArgs)
If e.Appointment IsNot Nothing AndAlso e.Appointment.Description.Contains("test") Then
e.Cancel = True
End If
If e.Event IsNot Nothing AndAlso e.Event.Status = "tentative" Then
e.Cancel = True
End If
End Sub
If you make different edits to both a Scheduler Appointment and a Google Calendar Event, the DXGoogleCalendarSynch component is unable to identify which of these objects holds valid data. To resolve such inconsistencies, the component fires DXGoogleCalendarSync.ConflictDetected events. Handle this event and set its ConflictDetectedEventArgs.GoogleEventIsValid parameter to false if a Scheduler Appointment is valid and should be copied into a Google Calendar.
private void dxGoogleCalendarSync1_ConflictDetected(object sender, ConflictDetectedEventArgs e) {
if (
//implement your condition here
//you can read the e.Appointment and e.Event parameters to compare conflicting objects
) {
e.GoogleEventIsValid = false;
}
}
Private Sub DxGoogleCalendarSync1_ConflictDetected(ByVal sender As Object, ByVal e As ConflictDetectedEventArgs)
If Then
'implement your condition here
'you can read the e.Appointment and e.Event parameters to compare conflicting objects
e.GoogleEventIsValid = False
End If
End Sub
If the DXGoogleCalendarSync.ConflictDetected event is not handled, the DXGoogleCalendarSync component always prioritizes Google Events over Scheduler Appointments when conflicts emerge.
Critical conflicts raise a different event, DXGoogleCalendarSync.OnException. Handle this event and read its e.Exception parameter to obtain conflict details.
Synchronization between Scheduler and Google calendars has the following limitations: