Binding to Business Objects
What if your scheduling data originates from somewhere other than an easily accessible database? An API that accesses a legacy system or an email based system are two examples that might fit this description. RadScheduler allows binding to objects of any arbitrary structure.
Binding to objects follows the same basic pattern as binding to database tables. You must assign a collection of objects to an instance of SchedulerBindingDataSource. You also need to define mappings so that the appointment data expected in the scheduler (Start, End, Subject, etc.) is satisfied by specific properties in the bound objects.
The code below is an example appointment. Keep in mind that the particular construction of the CustomAppointment class and the names of its properties are arbitrary. The mappings will decide where properties are used. Notice that the object implements the INotifyPropertyChanged interface. Without this interface implementation the populated appointment object data will not show up in the scheduler.
Copy[C#] Sample appointment class
public class CustomAppointment : INotifyPropertyChanged
{
private DateTime start = DateTime.Now;
private DateTime end = DateTime.Now;
private string subject = string.Empty;
private string description = string.Empty;
private string location = string.Empty;
private Guid id = Guid.NewGuid();
private List<CustomAppointment> exceptions;
public CustomAppointment()
{
}
public CustomAppointment(DateTime start, DateTime end, string subject, string description, string location)
{
this.start = start;
this.end = end;
this.subject = subject;
this.description = description;
this.location = location;
List<CustomAppointment> exceptions = new List<CustomAppointment>();
}
public List<CustomAppointment> Exceptions
{
get
{
return this.exceptions;
}
set
{
if (this.exceptions != value)
{
this.exceptions = value;
this.OnPropertyChanged("Exceptions");
}
}
}
public Guid Id
{
get
{
return this.id;
}
set
{
if (this.id != value)
{
this.id = value;
this.OnPropertyChanged("Id");
}
}
}
public DateTime Start
{
get
{
return this.start;
}
set
{
if (this.start != value)
{
this.start = value;
this.OnPropertyChanged("Start");
}
}
}
public DateTime End
{
get
{
return this.end;
}
set
{
if (this.end != value)
{
this.end = value;
this.OnPropertyChanged("End");
}
}
}
public string Subject
{
get
{
return this.subject;
}
set
{
if (this.subject != value)
{
this.subject = value;
this.OnPropertyChanged("Subject");
}
}
}
public string Description
{
get
{
return this.description;
}
set
{
if (this.description != value)
{
this.description = value;
this.OnPropertyChanged("Description");
}
}
}
public string Location
{
get
{
return this.location;
}
set
{
if (this.location != value)
{
this.location = value;
this.OnPropertyChanged("Location");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Copy[VB.NET] Sample appointment class
Public Class CustomAppointment
Implements INotifyPropertyChanged
Private _start As Date = Date.Now
Private _end As Date = Date.Now
Private _subject As String = String.Empty
Private _description As String = String.Empty
Private _location As String = String.Empty
Private _id As Guid = Guid.NewGuid()
Private _exceptions As List(Of CustomAppointment)
Public Sub New()
End Sub
Public Sub New(ByVal start As Date, ByVal [end] As Date, ByVal subject As String, ByVal description As String, ByVal location As String)
Me._start = start
Me._end = [end]
Me._subject = subject
Me._description = description
Me._location = location
Dim _exceptions As New List(Of CustomAppointment)()
End Sub
Public Property Exceptions() As List(Of CustomAppointment)
Get
Return Me._exceptions
End Get
Set(ByVal value As List(Of CustomAppointment))
If Me._exceptions IsNot value Then
Me._exceptions = value
Me.OnPropertyChanged("Exceptions")
End If
End Set
End Property
Public Property Id() As Guid
Get
Return Me._id
End Get
Set(ByVal value As Guid)
If Me._id <> value Then
Me._id = value
Me.OnPropertyChanged("Id")
End If
End Set
End Property
Public Property Start() As Date
Get
Return Me._start
End Get
Set(ByVal value As Date)
If Me._start <> value Then
Me._start = value
Me.OnPropertyChanged("Start")
End If
End Set
End Property
Public Property [End]() As Date
Get
Return Me._end
End Get
Set(ByVal value As Date)
If Me._end <> value Then
Me._end = value
Me.OnPropertyChanged("End")
End If
End Set
End Property
Public Property Subject() As String
Get
Return Me._subject
End Get
Set(ByVal value As String)
If Me._subject <> value Then
Me._subject = value
Me.OnPropertyChanged("Subject")
End If
End Set
End Property
Public Property Description() As String
Get
Return Me._description
End Get
Set(ByVal value As String)
If Me._description <> value Then
Me._description = value
Me.OnPropertyChanged("Description")
End If
End Set
End Property
Public Property Location() As String
Get
Return Me._location
End Get
Set(ByVal value As String)
If Me._location <> value Then
Me._location = value
Me.OnPropertyChanged("Location")
End If
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
If Me.PropertyChangedEvent IsNot Nothing Then
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End If
End SubTo use your custom object, create CustomAppointment instances and place them in a generic list before mapping and binding to the SchedulerBindingDataSource component.
Copy[C#] Binding to a list of business objects
BindingList<CustomAppointment> appointments = new BindingList<CustomAppointment>();
for (int i = 0; i < 10; i++)
{
if ((i % 2) == 0)
{
int appointmentNumber = i + 1;
CustomAppointment myAppointment =
new CustomAppointment(
DateTime.Now.AddHours(appointmentNumber),
DateTime.Now.AddHours(appointmentNumber + 2),
"Appointment " + appointmentNumber.ToString(),
"Description for Appointment " + appointmentNumber.ToString(),
"Conference room " + appointmentNumber.ToString());
appointments.Add(myAppointment);
}
}
SchedulerBindingDataSource dataSource = new SchedulerBindingDataSource();
AppointmentMappingInfo appointmentMappingInfo = new AppointmentMappingInfo();
appointmentMappingInfo.Start = "Start";
appointmentMappingInfo.End = "End";
appointmentMappingInfo.Summary = "Subject";
appointmentMappingInfo.Description = "Description";
appointmentMappingInfo.Location = "Location";
appointmentMappingInfo.UniqueId = "Id";
appointmentMappingInfo.Exceptions = "Exceptions";
dataSource.EventProvider.Mapping = appointmentMappingInfo;
dataSource.EventProvider.DataSource = appointments;
this.radScheduler1.DataSource = dataSource;
Copy[VB.NET] Binding to a list of business objects
Dim appointments As New BindingList(Of CustomAppointment)()
For i As Integer = 0 To 9
If (i Mod 2) = 0 Then
Dim appointmentNumber As Integer = i + 1
Dim myAppointment As New CustomAppointment(DateTime.Now.AddHours(appointmentNumber), DateTime.Now.AddHours(appointmentNumber + 2), "Appointment " + appointmentNumber.ToString(), "Description for Appointment " + appointmentNumber.ToString(), "Conference room " + appointmentNumber.ToString())
appointments.Add(myAppointment)
End If
Next
Dim dataSource As New SchedulerBindingDataSource()
Dim appointmentMappingInfo As New AppointmentMappingInfo()
appointmentMappingInfo.Start = "Start"
appointmentMappingInfo.[End] = "End"
appointmentMappingInfo.Summary = "Subject"
appointmentMappingInfo.Description = "Description"
appointmentMappingInfo.Location = "Location"
appointmentMappingInfo.UniqueId = "Id"
appointmentMappingInfo.Exceptions = "Exceptions"
dataSource.EventProvider.Mapping = appointmentMappingInfo
dataSource.EventProvider.DataSource = appointments
Me.radScheduler1.DataSource = dataSourceWhen the application is run, a series of CustomAppointment objects show up in the scheduler.
Grouping by resources
To use grouping by resource in this scenario, first you will need to create the business object that represents the resources:
Copy[C#] Create the resource object
public class CustomResource : INotifyPropertyChanged
{
private int id;
private string name;
public int Id
{
get
{
return this.id;
}
set
{
if (this.id != value)
{
this.id = value;
this.OnPropertyChanged("Id");
}
}
}
public string Name
{
get
{
return this.name;
}
set
{
if (this.name != value)
{
this.name = value;
this.OnPropertyChanged("Name");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Copy[VB.NET] Create the resource object
Public Class CustomResource
Implements INotifyPropertyChanged
Private m_id As Integer
Private m_name As String
Public Property Id() As Integer
Get
Return Me.m_id
End Get
Set(value As Integer)
If Me.m_id <> value Then
Me.m_id = value
Me.OnPropertyChanged("Id")
End If
End Set
End Property
Public Property Name() As String
Get
Return Me.m_name
End Get
Set(value As String)
If Me.m_name <> value Then
Me.m_name = value
Me.OnPropertyChanged("Name")
End If
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
End ClassNow we need to bind the ResourceProvider of SchedulerBindingDataSource to a collection of CustomResource objects:
Copy[C#] Bind the ResourceProvider
BindingList<CustomResource> resources = new BindingList<CustomResource>();
for (int i = 0; i < 5; i++)
{
CustomResource resource = new CustomResource();
resource.Id = i;
resource.Name = "Resource " + i;
resources.Add(resource);
}
ResourceMappingInfo resourceMappingInfo = new ResourceMappingInfo();
resourceMappingInfo.Name = "Name";
resourceMappingInfo.Id = "Id";
dataSource.ResourceProvider.Mapping = resourceMappingInfo;
dataSource.ResourceProvider.DataSource = resources;
Copy[VB.NET] Bind the ResourceProvider
Dim resources As New BindingList(Of CustomResource)()
For i As Integer = 0 To 4
Dim resource As New CustomResource()
resource.Id = i
resource.Name = "Resource " & i
resources.Add(resource)
Next
Dim resourceMappingInfo As New ResourceMappingInfo()
resourceMappingInfo.Name = "Name"
resourceMappingInfo.Id = "Id"
dataSource.ResourceProvider.Mapping = resourceMappingInfo
dataSource.ResourceProvider.DataSource = resourcesNext we need to create the relation between appointments and resources. We can create either one-to-many relation or many-to-many relation. The following two sections cover each of these scenarios.
One-to-many relation
To create a one-to-many relation between appointments and resources we need to add a property of type EventId to the business object that represents an appointment:
Copy[C#] Additional field and property to the CustomAppointment class
private EventId resourceId;
public EventId ResourceId
{
get
{
return this.resourceId;
}
set
{
if (this.resourceId != value)
{
this.resourceId = value;
this.OnPropertyChanged("ResourceId");
}
}
}
Copy[VB.NET] Additional field and property to the CustomAppointment class
Private _resourceId As EventId
Public Property ResourceId() As EventId
Get
Return Me._resourceId
End Get
Set(value As EventId)
If Not Object.Equals(Me._resourceId, value) Then
Me._resourceId = value
Me.OnPropertyChanged("ResourceId")
End If
End Set
End PropertyTo map the new property, add the following setting to your AppointmentMappingInfo instance:
Copy[C#]
appointmentMappingInfo.ResourceId = "ResourceId";
Copy[VB.NET]
appointmentMappingInfo.ResourceId = "ResourceId"
Note |
|---|
In this scenario you should not set the Resources property of the AppointmentMappingInfo |
Copy[C#]
CustomAppointment myAppointment =
new CustomAppointment(
DateTime.Now.AddHours(appointmentNumber),
DateTime.Now.AddHours(appointmentNumber + 2),
"Appointment " + appointmentNumber.ToString(),
"Description for Appointment " + appointmentNumber.ToString(),
"Conference room " + appointmentNumber.ToString());
appointments.Add(myAppointment);
myAppointment.ResourceId = new EventId(i % 2);
Copy[VB.NET]
Dim myAppointment As New CustomAppointment(DateTime.Now.AddHours(appointmentNumber), DateTime.Now.AddHours(appointmentNumber + 2), "Appointment " + appointmentNumber.ToString(), "Description for Appointment " + appointmentNumber.ToString(), "Conference room " + appointmentNumber.ToString())
appointments.Add(myAppointment)
To test this scenario, assign each appointment with a ResourceId and enable grouping by setting RadScheduler’s GroupType property:
Copy[C#]
this.radScheduler1.GroupType = GroupType.Resource;
Copy[VB.NET]
Me.radScheduler1.GroupType = GroupType.Resource
Many-to-many relation
This scenario can be implemented similarly to the previous one. Instead of the ResourceId property, we should add a Resources property which represents a collection of EventId objects:
Copy[C#] Additional field and property to the CustomAppointment class
private List<EventId> resources = new List<EventId>();
public List<EventId> Resources
{
get
{
return this.resources;
}
set
{
if (this.resources != value)
{
this.resources = value;
this.OnPropertyChanged("Resources");
}
}
}
Copy[VB.NET] Additional field and property to the CustomAppointment class
Private _resources As New List(Of EventId)
Public Property Resources() As List(Of EventId)
Get
Return Me._resources
End Get
Set(value As List(Of EventId))
If Not Me._resources.Equals(value) Then
Me._resources = value
Me.OnPropertyChanged("Resources")
End If
End Set
End PropertyIn the AppointmentMappingInfo settings the ResourceId property should be left unset and the Resources property should be set with the name of the collection:
Copy[C#]
appointmentMappingInfo.Resources = "Resources";
Copy[VB.NET]
appointmentMappingInfo.Resources = "Resources"
Now we can add a resource to an appointment by adding its id in the Resources collection of our business objects:
Copy[C#]
myAppointment.Resources.Add(new EventId(resources[i%3].Id));
Copy[VB.NET]
myAppointment.Resources.Add(New EventId(resources(i Mod 3).Id))