The ASPxScheduler appears to be designed so that you must load all your appointments into its storage engine. From storage engine, the control will then filter those appointments based on the current ActiveView. That is great if you have 10 appointments, but what about large appointment datasets? What about 5 years of appointments? What about hundreds of thousands of appointments? Based on their own examples, the easiest way to do this is to restrict the user to a large enough dataset to be useful, without pulling too much data (e.g. the current week or month), but that isn't exactly flexible. It also means you are loading data unnecessarily, assuming most users might only view today's appointments when you loaded a month's worth of appointments.
Using the ListBoundMode demo as a base, I have altered their call into their random data generator, and pulled data from my own database instead. I used custom object collections as they suggest (see code below).
Now, to get the selected start and end dates, you would think it would be fairly simple. Specifically I need to know the following two dates to be able to load my data:
The problem is that I simply CANNOT find these values during this stage of the control's lifecycle. Hence, when I call LoadCustomEventList(), though I can get the previously selected dates (from the previous postback), I cannot get the newly selected time interval. Does anyone know which properties might hold this information, and at this point in the conrol's lifecycle? I've meandered though the debugger, but I can't find anything useful.
There is of course another event that might be useful: the OnActiveViewChanged event. However, this gets called after my ObjectDataSet has been created, so my only option is to reload the data based on the newly selected start and end date (which is now correctly available). The problem with this is that you end up loading two sets of data, the first being a waste of time.
I simply cannot make sense of this control. If I load all the appointments in my database, I'll get ~10,000 appointments per user group, which based on their own example, gets stored in a session value and reloaded every postback or callback. With 500 concurrent users, that is pretty quickly going to kill our servers.
We are evaluating this control in comparison to Infragistics (which is also pretty fiddly to work with), but if I can't solve this one, we'll have to go back to Infragistics.
I welcome any suggestions.
Regards
Ben
P.S. I tried out FetchAppointments already, but it gets called multiple times.
Anyway, code is here:
protected void appointmentsDataSource_ObjectCreated(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = new CustomEventDataSource(GetCustomEvents());
}
private CustomEventList GetCustomEvents()
{
/*CustomEventList events = Session["CustomEventList"] as CustomEventList;
if (events == null)
{
events = LoadCustomEventList();
Session["CustomEventList"] = events;
}
return events;*/
return LoadCustomEventList();
}
private CustomEventList LoadCustomEventList()
{
DateTime dtStart = this.ASPxScheduler1.ActiveView.GetVisibleIntervals().Start; // This gives the wrong value
DateTime dtEnd = this.ASPxScheduler1.ActiveView.GetVisibleIntervals().End; // This gives the wrong value
List<Appointment> entities = AppointmentBusinessService.Instance.Find(dtStart, dtEnd);
CustomEventList events = new CustomEventList();
foreach (Appointment entity in entities)
{
CustomEvent evt = new CustomEvent();
evt.Id = entity.AppointmentId;
evt.AppointmentId = entity.AppointmentId;
evt.StartTime = entity.DateStart;
evt.EndTime = entity.DateEnd;
evt.EventType = 0; // Normal
evt.Label = 0; // Different types different colours
TimeSpan ts = entity.DateEnd - entity.DateStart;
evt.AllDay = (ts.TotalDays > 1) ? true : false;
evt.Location = "No location";
evt.Subject = entity.EventTypeText;
evt.Status = 1;
evt.Description = "None";
// Get users
CustomResourceList assigned = new CustomResourceList();
foreach (AppointmentUserAccount account in entity.AppointmentUserAccountCollection)
{
UserAccount acc = UserBusinessService.Instance.GetByUserAccountId(account.UserAccountId);
CustomResource user = new CustomResource();
user.Id = acc.UserAccountId;
user.ResourceId = acc.UserAccountId;
user.ResourceName = acc.DisplayTitle;
assigned.Add(user);
}
evt.Resources = assigned;
events.Add(evt);
}
return events;
}
protected void ASPxScheduler1_ActiveViewChanged(object sender, EventArgs e)
{
this.ASPxScheduler1.DataBind();
}