This example demonstrates how to handle the FetchAppointments event to limit the number of appointments fetched from the data source. The Scheduler Control is bound to a collection of custom objects.
Do not set the SchedulerStorage.Appointments
or SchedulerStorage.Appointments.DataSource
property in the FetchAppointments
event handler. Update the collection (add/remove items) that is assigned to the SchedulerStorage.Appointments.DataSource
property.
Read the following help topic for additional information: FetchAppointments Event - Handling Large Datasets.
Files to Review
- CustomObjects.cs (VB: CustomObjects.vb)
- Form1.cs (VB: Form1.vb)
See Also
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
C#using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Drawing;
namespace SchedulerFetchCustomObjects {
#region #customappointment
public class CustomAppointment : IEditableObject {
DateTime fStart;
DateTime fEnd;
string fSubject;
int fStatus;
string fDescription;
long fLabel;
string fLocation;
bool fAllday;
int fEventType;
string fRecurrenceInfo;
string fReminderInfo;
object fOwnerId;
CustomEventList events;
bool committed = false;
public CustomAppointment(CustomEventList events) {
this.events = events;
}
private void OnListChanged() {
int index = events.IndexOf(this);
events.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
}
public DateTime StartTime { get { return fStart; } set { fStart = value; } }
public DateTime EndTime { get { return fEnd; } set { fEnd = value; } }
public string Subject { get { return fSubject; } set { fSubject = value; } }
public int Status { get { return fStatus; } set { fStatus = value; } }
public string Description { get { return fDescription; } set { fDescription = value; } }
public long Label { get { return fLabel; } set { fLabel = value; } }
public string Location { get { return fLocation; } set { fLocation = value; } }
public bool AllDay { get { return fAllday; } set { fAllday = value; } }
public int EventType { get { return fEventType; } set { fEventType = value; } }
public string RecurrenceInfo { get { return fRecurrenceInfo; } set { fRecurrenceInfo = value; } }
public string ReminderInfo { get { return fReminderInfo; } set { fReminderInfo = value; } }
public object OwnerId { get { return fOwnerId; } set { fOwnerId = value; } }
public void BeginEdit() {
}
public void CancelEdit() {
if (!committed) {
((IList)events).Remove(this);
}
}
public void EndEdit() {
committed = true;
}
}
#endregion #customappointment
#region #customeventlist
public class CustomEventList : CollectionBase, IBindingList {
public CustomAppointment this[int idx] { get { return (CustomAppointment)base.List[idx]; } }
public new void Clear() {
base.Clear();
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
public void Add(CustomAppointment appointment) {
base.List.Add(appointment);
}
public int IndexOf(CustomAppointment appointment) {
return List.IndexOf(appointment);
}
public object AddNew() {
CustomAppointment app = new CustomAppointment(this);
List.Add(app);
return app;
}
public bool AllowEdit { get { return true; } }
public bool AllowNew { get { return true; } }
public bool AllowRemove { get { return true; } }
private ListChangedEventHandler listChangedHandler;
public event ListChangedEventHandler ListChanged {
add { listChangedHandler += value; }
remove { listChangedHandler -= value; }
}
internal void OnListChanged(ListChangedEventArgs args) {
if (listChangedHandler != null) {
listChangedHandler(this, args);
}
}
protected override void OnRemoveComplete(int index, object value) {
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
}
protected override void OnInsertComplete(int index, object value) {
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
}
public void AddIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
public void ApplySort(PropertyDescriptor pd, ListSortDirection dir) { throw new NotSupportedException(); }
public int Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); }
public bool IsSorted { get { return false; } }
public void RemoveIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
public void RemoveSort() { throw new NotSupportedException(); }
public ListSortDirection SortDirection { get { throw new NotSupportedException(); } }
public PropertyDescriptor SortProperty { get { throw new NotSupportedException(); } }
public bool SupportsChangeNotification { get { return true; } }
public bool SupportsSearching { get { return false; } }
public bool SupportsSorting { get { return false; } }
}
#endregion #customeventlist
#region #customresource
public class CustomResource {
string name;
int res_id;
Color res_color;
public string Name { get { return name; } set { name = value; } }
public int ResID { get { return res_id; } set { res_id = value; } }
public Color ResColor { get { return res_color; } set { res_color = value; } }
public CustomResource() {
}
}
#endregion #customresource
#region #customresourcecollection
public class CustomResourceCollection : CollectionBase, IBindingList {
public CustomResourceCollection() {
}
public CustomResource this[int idx] { get { return (CustomResource)base.List[idx]; } }
public void Add(CustomResource res) {
List.Add(res);
}
public new void Clear() {
base.Clear();
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
protected override void OnRemoveComplete(int index, object value) {
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
}
protected override void OnInsertComplete(int index, object value) {
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
}
#region IBindingList implementation
ListChangedEventHandler listChangedHandler;
public event ListChangedEventHandler ListChanged { add { listChangedHandler += value; } remove { listChangedHandler -= value; } }
internal void OnListChanged(ListChangedEventArgs args) {
if (listChangedHandler != null) listChangedHandler(this, args);
}
public bool AllowEdit { get { return true; } }
public bool AllowNew { get { return true; } }
public bool AllowRemove { get { return true; } }
public bool IsSorted { get { return false; } }
public ListSortDirection SortDirection { get { throw new NotSupportedException(); } }
public PropertyDescriptor SortProperty { get { throw new NotSupportedException(); } }
public bool SupportsChangeNotification { get { return true; } }
public bool SupportsSearching { get { return false; } }
public bool SupportsSorting { get { return false; } }
public object AddNew() {
CustomResource res = new CustomResource();
Add(res);
return res;
}
public void AddIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
public void ApplySort(PropertyDescriptor pd, ListSortDirection dir) { throw new NotSupportedException(); }
public int Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); }
public void RemoveIndex(PropertyDescriptor pd) { throw new NotSupportedException(); }
public void RemoveSort() { throw new NotSupportedException(); }
#endregion
}
#endregion #customresourcecollection
}
C#using System;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraScheduler;
namespace SchedulerFetchCustomObjects {
public partial class Form1 : Form {
public static Random RandomInstance = new Random();
// List with all data items (database imitation)
private CustomEventList fullDataSource = new CustomEventList();
private TimeInterval lastFetchedInterval = new TimeInterval();
public Form1() {
InitializeComponent();
schedulerStorage1.Resources.ColorSaving = ColorSavingType.Color;
}
private void Form1_Load(object sender, EventArgs e) {
InitResources();
InitAppointments();
schedulerControl1.Start = DateTime.Today;
UpdateOptions();
}
#region Resources generation
void InitResources() {
ResourceMappingInfo mappings = this.schedulerStorage1.Resources.Mappings;
mappings.Id = "ResID";
mappings.Color = "ResColor";
mappings.Caption = "Name";
CustomResourceCollection customResourceCollection = new CustomResourceCollection();
customResourceCollection.Add(CreateCustomResource(1, "Max Fowler", Color.PowderBlue));
customResourceCollection.Add(CreateCustomResource(2, "Nancy Drewmore", Color.PaleVioletRed));
customResourceCollection.Add(CreateCustomResource(3, "Pak Jang", Color.PeachPuff));
this.schedulerStorage1.Resources.DataSource = customResourceCollection;
}
CustomResource CreateCustomResource(int res_id, string caption, Color ResColor) {
CustomResource cr = new CustomResource();
cr.ResID = res_id;
cr.Name = caption;
cr.ResColor = ResColor;
return cr;
}
#endregion
#region Appointments generation
void InitAppointments() {
AppointmentMappingInfo mappings = this.schedulerStorage1.Appointments.Mappings;
mappings.Start = "StartTime";
mappings.End = "EndTime";
mappings.Subject = "Subject";
mappings.AllDay = "AllDay";
mappings.Description = "Description";
mappings.Label = "Label";
mappings.Location = "Location";
mappings.RecurrenceInfo = "RecurrenceInfo";
mappings.ReminderInfo = "ReminderInfo";
mappings.ResourceId = "OwnerId";
mappings.Status = "Status";
mappings.Type = "EventType";
// Ppulate the fullDataSource with data items
GenerateEvents(fullDataSource);
// Local data list that will be populated in the FetchAppointments evet handler
CustomEventList actualDataSource = new CustomEventList();
this.schedulerStorage1.Appointments.DataSource = actualDataSource;
}
void GenerateEvents(CustomEventList eventList) {
int count = schedulerStorage1.Resources.Count;
for (int i = 0; i < 100; i++) {
Resource resource = schedulerStorage1.Resources[i % count];
string subjPrefix = resource.Caption + "'s ";
eventList.Add(CreateEvent(eventList, subjPrefix + "meeting", resource.Id, 2, 5));
eventList.Add(CreateEvent(eventList, subjPrefix + "travel", resource.Id, 3, 6));
eventList.Add(CreateEvent(eventList, subjPrefix + "phone call", resource.Id, 0, 10));
}
}
CustomAppointment CreateEvent(CustomEventList eventList, string subject, object resourceId, int status, int label) {
CustomAppointment apt = new CustomAppointment(eventList);
apt.Subject = subject;
apt.OwnerId = resourceId;
Random rnd = RandomInstance;
int rangeInMinutes = 60 * 24;
apt.StartTime = DateTime.Today + TimeSpan.FromHours(rnd.Next(0, rangeInMinutes));
apt.EndTime = apt.StartTime + TimeSpan.FromMinutes(60);
apt.Status = status;
apt.Label = label;
return apt;
}
#endregion
private void schedulerStorage1_FetchAppointments(object sender, FetchAppointmentsEventArgs e) {
DateTime start = e.Interval.Start;
DateTime end = e.Interval.End;
CustomEventList actualDataSource = this.schedulerStorage1.Appointments.DataSource as CustomEventList;
if (actualDataSource == null)
return;
// Check if the requested interval is outside lastFetchedInterval
if (start <= lastFetchedInterval.Start || end >= lastFetchedInterval.End) {
// You can vary margin value to find the most appropriate balance between performance and detalization
TimeSpan margin = TimeSpan.FromDays(0); // TimeSpan.FromDays(1)
lastFetchedInterval = new TimeInterval(start - margin, end + margin);
// Poplate the actualDataSource using the lastFetchedInterval
actualDataSource.Clear();
for (int i = 0; i < fullDataSource.Count; i++) {
CustomAppointment customAppointment = fullDataSource[i];
if (customAppointment.StartTime >= lastFetchedInterval.Start.Date &&
customAppointment.EndTime <= lastFetchedInterval.End.Date) {
actualDataSource.Add(customAppointment);
}
}
}
lblInfo.Text = string.Format("Interval: {0}, Appointments: {1}", lastFetchedInterval, actualDataSource.Count.ToString());
}
private void cbBoldAppointmentDates_CheckedChanged(object sender, EventArgs e) {
UpdateOptions();
}
private void UpdateOptions() {
dateNavigator1.BoldAppointmentDates = cbBoldAppointmentDates.Checked;
}
}
}