Example E3370
Visible to All Users

WinForms Scheduler - Fetch appointments when binding to custom objects

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

See Also

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

CustomObjects.cs(vb)
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 }
Form1.cs(vb)
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; } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.