This document describes how to create a custom form and replace the standard appointment recurrence editing form with a newly created form. Method 2 uses the System.Windows.Forms.Form and the AppointmentFormController.
To create a custom form, add a new form to the project and name it MyAppointmentRecurrentForm.
There are six recurrence types (refer to the RecurrenceType topic) and four ready-to-use recurrent controls suitable for most situations. To add required controls to the form, perform the following steps:
- Select the GroupControl in the Toolbox and drop it onto the MyAppointmentRecurrentForm. Change its visibility to false.
- Drag the DailyRecurrenceControl from the Toolbox and drop it on the GroupControl. Place it over the previous control. Change its visibility to false.
- Drag the WeeklyRecurrenceControl from the Toolbox and drop it on the GroupControl. Place it over the previous control. Change its visibility to false.
- Drag the MonthlyRecurrenceControl from the Toolbox and drop it on the GroupControl. Place it over the previous control. Change its visibility to false.
- Drag the YearlyRecurrenceControl from the Toolbox and drop it on the GroupControl. Place it over the previous control. Change its visibility to false.
- Select the RadioGroup control in the Toolbox and drop it on the form. Add four items to the control with the RadioGroupItem.Description values set to Daily, Weekly, Monthly and Yearly. Specify these strings as the RadioGroupItem.Value property values.
- Add OK and Cancel buttons.
The form will look like that shown in the following picture.
Add the code to the code behind file as illustrated in the following example.
Show Me
A complete sample project is available in the DevExpress Code Examples database at http://www.devexpress.com/example=T222451.
The code below is an example of the custom recurrent appointment editing form. Invoke it for recurring appointments. This form allows changing recurrence options only. To change start/end times and durations, add other controls to the form.
Handle the SchedulerControl.EditAppointmentFormShowing event to invoke a custom form instead of the default AppointmentForm.
C# Form1.cs
using System;
using System.Windows.Forms;
namespace CustomRecurrenceFormWinFormSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Handle the EditAppointmentFormShowing event to invoke a custom form instead of the default appointment editing form.
this.schedulerControl1.EditAppointmentFormShowing += schedulerControl1_EditAppointmentFormShowing;
this.Shown += Form1_Shown;
}
void schedulerControl1_EditAppointmentFormShowing(object sender, DevExpress.XtraScheduler.AppointmentFormEventArgs e)
{
MyAppointmentRecurrenceForm myForm = new MyAppointmentRecurrenceForm(schedulerControl1, e.Appointment);
myForm.ShowDialog();
e.Handled = true;
}
void Form1_Shown(object sender, EventArgs e)
{
this.schedulerControl1.CreateAppointment(false, true);
}
}
}
C#:MyAppointmentRecurrenceForm .cs
using DevExpress.XtraScheduler;
using DevExpress.XtraScheduler.UI;
using System;
using System.Windows.Forms;
namespace CustomRecurrenceFormWinFormSample
{
public partial class MyAppointmentRecurrenceForm : Form
{
private RecurrenceControlBase currentRecurrenceControl;
private IRecurrenceInfo rinfo;
private AppointmentFormController controller;
private Appointment patternCopy;
private FirstDayOfWeek firstDayOfWeek;
protected int suspendUpdateCount;
protected bool IsUpdateSuspended { get { return suspendUpdateCount > 0; } }
public MyAppointmentRecurrenceForm(SchedulerControl scheduler_control,
Appointment apt)
{
InitializeComponent();
// Create a controller instance.
controller = new AppointmentFormController(scheduler_control, apt);
// Get an appointment pattern copy.
patternCopy = controller.PrepareToRecurrenceEdit();
// Get access to the recurrence information.
this.rinfo = patternCopy.RecurrenceInfo;
// Get the first day of the week.
firstDayOfWeek = scheduler_control.OptionsView.FirstDayOfWeek;
radioGroup1.EditValueChanged += radioGroup1_EditValueChanged;
btnOK.Click += btnOK_Click;
btnCancel.Click += btnCancel_Click;
InitializeControls(firstDayOfWeek);
}
#region #initialization
protected virtual void InitializeControls(FirstDayOfWeek firstDayOfWeek)
{
InitRecurrenceControls(firstDayOfWeek);
// Prevent settings from being reset.
SuspendUpdate();
SetRecurrenceType(rinfo.Type);
ResumeUpdate();
}
protected virtual void InitRecurrenceControls(FirstDayOfWeek firstDayOfWeek)
{
weeklyRecurrenceControl1.FirstDayOfWeek = firstDayOfWeek;
dailyRecurrenceControl1.RecurrenceInfo = rinfo;
weeklyRecurrenceControl1.RecurrenceInfo = rinfo;
monthlyRecurrenceControl1.RecurrenceInfo = rinfo;
yearlyRecurrenceControl1.RecurrenceInfo = rinfo;
}
protected virtual void SuspendUpdate()
{
suspendUpdateCount++;
}
protected virtual void ResumeUpdate()
{
if (suspendUpdateCount > 0)
suspendUpdateCount--;
}
#endregion #initialization
#region #reset
protected virtual void ResetRecurrenceInfo()
{
RecurrenceType type = GetRecurrenceType();
Reset(type);
}
protected virtual RecurrenceType GetRecurrenceType()
{
switch (radioGroup1.EditValue.ToString()) {
case "Daily":
return RecurrenceType.Daily;
case "Weekly":
return RecurrenceType.Weekly;
case "Monthly":
return RecurrenceType.Monthly;
default:
return RecurrenceType.Yearly;
}
}
protected virtual void SetRecurrenceType(RecurrenceType type)
{
switch (type)
{
case RecurrenceType.Daily:
radioGroup1.EditValue = "Daily";
break;
case RecurrenceType.Weekly:
radioGroup1.EditValue = "Weekly";
break;
case RecurrenceType.Monthly:
radioGroup1.EditValue = "Monthly";;
break;
case RecurrenceType.Yearly:
radioGroup1.EditValue = "Yearly";
break;
}
}
internal void Reset(RecurrenceType type)
{
switch (type)
{
case RecurrenceType.Daily:
rinfo.Type = RecurrenceType.Daily;
rinfo.WeekDays = WeekDays.EveryDay;
break;
case RecurrenceType.Weekly:
rinfo.Type = RecurrenceType.Weekly;
rinfo.WeekDays = DevExpress.XtraScheduler.Native.DateTimeHelper.ToWeekDays(rinfo.Start.DayOfWeek);
break;
case RecurrenceType.Monthly:
rinfo.Type = RecurrenceType.Monthly;
rinfo.WeekOfMonth = WeekOfMonth.None;
rinfo.DayNumber = rinfo.Start.Day;
break;
case RecurrenceType.Yearly:
rinfo.Type = RecurrenceType.Yearly;
rinfo.WeekOfMonth = WeekOfMonth.None;
rinfo.DayNumber = rinfo.Start.Day;
rinfo.Month = rinfo.Start.Month;
rinfo.WeekDays = DevExpress.XtraScheduler.Native.DateTimeHelper.ToWeekDays(rinfo.Start.DayOfWeek);
break;
}
rinfo.Periodicity = 1;
}
protected virtual void ChangeCurrentRecurrenceControl()
{
if (currentRecurrenceControl != null)
currentRecurrenceControl.Visible = false;
switch (GetRecurrenceType())
{
case RecurrenceType.Daily:
currentRecurrenceControl = dailyRecurrenceControl1;
break;
case RecurrenceType.Weekly:
currentRecurrenceControl = weeklyRecurrenceControl1;
break;
case RecurrenceType.Monthly:
currentRecurrenceControl = monthlyRecurrenceControl1;
break;
case RecurrenceType.Yearly:
currentRecurrenceControl = yearlyRecurrenceControl1;
break;
}
currentRecurrenceControl.Visible = true;
}
#endregion #reset
#region #events
// Events section.
void radioGroup1_EditValueChanged(object sender, EventArgs e)
{
OnRecurrenceTypeEditValueChanged();
}
protected virtual void OnRecurrenceTypeEditValueChanged()
{
if (!IsUpdateSuspended)
ResetRecurrenceInfo();
ChangeCurrentRecurrenceControl();
currentRecurrenceControl.UpdateControls();
}
void btnOK_Click(object sender, System.EventArgs e)
{
ValidationArgs args = new ValidationArgs();
currentRecurrenceControl.ValidateValues(args);
if (args.Valid)
{
args = new ValidationArgs();
currentRecurrenceControl.CheckForWarnings(args);
if (!args.Valid)
{
DialogResult answer = MessageBox.Show(this, args.ErrorMessage,
Application.ProductName, MessageBoxButtons.OKCancel,
MessageBoxIcon.Question);
if (answer == DialogResult.OK)
this.DialogResult = DialogResult.OK;
else
{
if (args.Control != null)
((Control)args.Control).Focus();
}
}
else
// Apply changes to the appointment recurrence pattern.
controller.ApplyRecurrence(patternCopy);
// Apply changes to the original appointment.
controller.ApplyChanges();
this.DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show(this, args.ErrorMessage, Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
if (args.Control != null)
((Control)args.Control).Focus();
}
}
void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
#endregion #events
}
}
C#:Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CustomRecurrenceFormWinFormSample
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Some comments are given below to clarify the interaction logic.
- To edit an appointment, the AppointmentFormController object is required. Use its AppointmentModificationControllerBase.PrepareToRecurrenceEditmethod, to obtain a copy of the recurrence pattern for this appointment. All changes are applied to the appointment’s copy only. The AppointmentModificationControllerBase.ApplyRecurrence method should be called to alter an instance of the appointment recurrence pattern. To send the changes back to the original instance of the appointment, call the AppointmentModificationControllerBase.ApplyChanges method.
- Since several recurrence controls refer to week days, select the first day of the week for their proper initialization. The first day of the week setting is a scheduler option, available via SchedulerOptionsViewBase.FirstDayOfWeek.
- The recurrence controls are linked to the RecurrenceInfo object. To display changes of this object, call the corresponding RecurrenceControlBase.UpdateControls method of the control.
- The code example contains DevExpress.XtraScheduler.Native.DateTimeHelper methods. This is an internal object, used for the date-time type conversion. In your code, you can utilize another methods for the type conversion.
- When the user clicks “OK”, the control’s edited values are validated by calling the RecurrenceControlBase.ValidateValues method. This method is specific to a control, and usually checks whether the value is a positive integer, not more than 31, whether it’s a day number and so on. In case of any problem, a dialog window is displayed. Some settings may have side effects, so the RecurrenceControlBase.CheckForWarnings procedure is called, to show warnings to the user.