In this blog post I am showing how to create a custom RadScheduler control that can be used to insert/update and delete content items. Generally the implementation is related to Events provider and IEvent objects. All data for the items managed through this control is persisted by the default Events provider.
We need to implement several properties
- ProviderName - Name of the provider
- LayoutTemplatePath - Gets or sets the url to EventsScheduleViewCustom template.
- LayoutTemplate- Gets or sets EventsScheduleViewCustom template
- SingleEventUrl - Url of the page where single event will be displayed. That page should contain EventView control.
- OnInit- Overrides the base method and registers ControlDesignerBase control as one whose control state must be persisted.
- LoadControlState - Restores control state information from a previous page request that was saved by the SaveControlState
- SaveControlState - Saves server control state changes
- CreateChildControls -called to populate the child control hierarchy. Here we use ObjectDataSourceControl and call all EventsScheduleView to Insert/Update/Delete Event items.
- EventsSchedule_AppointmentDelete
- EventsSchedule_AppointmentInsert
- EventsSchedule_AppointmentUpdate- EventsSchedule_AppointmentCreated
- GetItemUrl - Getting the item url that will be used in EventsView control
EventsScheduleViewContainer
RadScheduler declaration and control template
- in the template I have
<telerik:RadAjaxManagerProxy runat="server" ID="RadAjaxManagerProxy1"> |
<AjaxSettings> |
<telerik:AjaxSetting AjaxControlID="eventsSchedule"> |
<UpdatedControls> |
<telerik:AjaxUpdatedControl ControlID="eventsSchedule" LoadingPanelID="RadAjaxLoadingPanel1" /> |
</UpdatedControls> |
</telerik:AjaxSetting> |
</AjaxSettings> |
</telerik:RadAjaxManagerProxy> |
<telerik:RadScheduler ID="eventsSchedule" runat="server" Skin="WebBlue" Width="500" Height="500"> |
<AppointmentContextMenuSettings EnableDefault="true" /> |
<TimeSlotContextMenuSettings EnableDefault="true" /> |
<AppointmentTemplate> |
<asp:HyperLink id="eventDetailsLink" runat="server" /> |
</AppointmentTemplate> |
</telerik:RadScheduler> |
using System; |
using System.Web.UI.WebControls; |
using Telerik.Events; |
using Telerik.Events.WebControls; |
using System.Linq; |
using System.Collections.Generic; |
using Telerik.Web.UI; |
using Telerik.Cms.Web.UI; |
using System.ComponentModel; |
using System.Web.UI; |
using Telerik.Framework.Web; |
using Telerik.Cms.Engine; |
using Telerik; |
using System.Web; |
using Telerik.Web; |
using Telerik.Cms.Engine.WebControls; |
/// <summary> |
/// Summary description for MyEventsScheduleView |
/// </summary> |
public class EventsScheduleViewCustom : CompositeControl |
{ |
#region Properties |
[System.ComponentModel.Category("Data")] |
public string ProviderName |
{ |
get |
{ |
string obj = (string)this.ViewState["ProviderName"]; |
if (string.IsNullOrEmpty(obj)) |
return "Events"; |
return (string)obj; |
} |
set |
{ |
this.ViewState["ProviderName"] = value; |
} |
} |
[WebEditor("Telerik.FileManager.UrlWebEditor, Telerik.FileManager"), |
System.ComponentModel.Category("Appearance"), |
System.Web.UI.Themeable(false), |
DefaultValue("")] |
public virtual string LayoutTemplatePath |
{ |
get |
{ |
object obj = this.ViewState["EventsScheduleViewTemplatePath"]; |
if (obj == null) |
return "~/Sitefinity/ControlTemplates/Events/EventsScheduleView.ascx"; |
return (string)obj; |
} |
set |
{ |
this.ViewState["EventsScheduleViewTemplatePath"] = value; |
} |
} |
[Browsable(false), |
System.Web.UI.PersistenceMode(PersistenceMode.InnerProperty), |
DefaultValue(typeof(ITemplate), ""), |
Description("Events Schedule View template"), |
TemplateContainer(typeof(EventsScheduleView)) |
] |
public virtual ITemplate LayoutTemplate |
{ |
get |
{ |
if (layoutTemplate == null) |
layoutTemplate = ControlUtils.GetTemplate<DefaultTemplate>(LayoutTemplatePath); |
return layoutTemplate; |
} |
set |
{ |
layoutTemplate = value; |
} |
} |
[WebEditor("Telerik.Cms.Web.UI.UrlEditorWrapper, Telerik.Cms"), |
Category("Behavior")] |
public virtual string SingleEventUrl |
{ |
get |
{ |
object obj = ViewState["SingleEventUrl"]; |
if (obj != null) |
return (string)obj; |
return String.Empty; |
} |
set |
{ |
ViewState["SingleEventUrl"] = value; |
} |
} |
#endregion |
#region Overriden Methods |
protected override void OnInit(EventArgs e) |
{ |
base.OnInit(e); |
if (base.Page != null) |
base.Page.RegisterRequiresControlState(this); |
if (String.IsNullOrEmpty(providerName)) |
providerName = EventsManager.DefaultContentProvider; |
if (!String.IsNullOrEmpty(providerName)) |
{ |
if (eventsManager == null || eventsManager.Provider.Name != providerName) |
eventsManager = new EventsManager(providerName); |
} |
} |
/// <summary> |
/// Gets the HTML tag for the ListDisplay. |
/// </summary> |
protected override HtmlTextWriterTag TagKey |
{ |
get |
{ |
return HtmlTextWriterTag.Div; |
} |
} |
protected override void LoadControlState(object savedState) |
{ |
if (savedState != null) |
{ |
object[] state = (object[])savedState; |
providerName = (string)state[0]; |
from = (DateTime)state[1]; |
to = (DateTime)state[2]; |
} |
} |
protected override object SaveControlState() |
{ |
return new object[] { |
providerName, |
from, |
to |
}; |
} |
protected override void OnPreRender(EventArgs e) |
{ |
base.OnPreRender(e); |
} |
protected override void CreateChildControls() |
{ |
Controls.Clear(); |
if (Page == null || DesignMode) |
{ |
Label noDesignModeLabel = new Label(); |
noDesignModeLabel.Text = "The control cannot be previewed in design mode."; |
Controls.Add(noDesignModeLabel); |
} |
else |
{ |
container = new EventsScheduleViewContainer(this); |
LayoutTemplate.InstantiateIn(container); |
ObjectDataSource dataSource = new ObjectDataSource(); |
dataSource.ID = "EventsDataSource"; |
dataSource.TypeName = "Telerik.Events.EventsManager"; |
dataSource.SelectMethod = "GetEvents"; |
dataSource.SelectParameters.Add("from", TypeCode.DateTime, from.ToString()); |
dataSource.SelectParameters.Add("to", TypeCode.DateTime, to.ToString()); |
dataSource.SelectParameters.Add("sortExpression", String.Empty); |
dataSource.SelectParameters.Add("status", ContentStatus.Published.ToString()); |
dataSource.ObjectCreating += new ObjectDataSourceObjectEventHandler(dataSource_ObjectCreating); |
dataSource.Selecting += new ObjectDataSourceSelectingEventHandler(dataSource_Selecting); |
Controls.Add(dataSource); |
container.EventsSchedule.DataSourceID = dataSource.ID; |
container.EventsSchedule.DataKeyField = "ID"; |
container.EventsSchedule.DataSubjectField = "EventTitle"; |
container.EventsSchedule.DataStartField = "Start"; |
container.EventsSchedule.DataEndField = "End"; |
// allow delete, insert and edit. |
container.EventsSchedule.AllowDelete = true; |
container.EventsSchedule.AllowInsert = true; |
container.EventsSchedule.AllowEdit = true; |
container.EventsSchedule.AppointmentUpdate += new AppointmentUpdateEventHandler(EventsSchedule_AppointmentUpdate); |
container.EventsSchedule.AppointmentInsert += new AppointmentInsertEventHandler(EventsSchedule_AppointmentInsert); |
container.EventsSchedule.AppointmentDelete += new AppointmentDeleteEventHandler(EventsSchedule_AppointmentDelete); |
container.EventsSchedule.AppointmentCreated += new AppointmentCreatedEventHandler(EventsSchedule_AppointmentCreated); |
Controls.Add(container); |
} |
} |
void EventsSchedule_AppointmentDelete(object sender, SchedulerCancelEventArgs e) |
{ |
var eventsManager = new EventsManager("Events"); |
IEvent deleteEvent = eventsManager.GetEvent(new Guid(e.Appointment.ID.ToString())); |
eventsManager.DeleteEvent(deleteEvent.ID, true); |
} |
void EventsSchedule_AppointmentInsert(object sender, SchedulerCancelEventArgs e) |
{ |
var eventsManager = new EventsManager("Events"); |
IContent newEvent = eventsManager.Content.CreateContent("text/html"); |
newEvent.Content = e.Appointment.Subject; |
newEvent.SetMetaData("Title", e.Appointment.Subject); |
newEvent.SetMetaData("Event_Start", e.Appointment.Start); |
newEvent.SetMetaData("Event_End", e.Appointment.End); |
eventsManager.Content.SaveContent(newEvent, ContentStatus.Published); |
} |
void EventsSchedule_AppointmentUpdate(object sender, AppointmentUpdateEventArgs e) |
{ |
var eventsManager = new EventsManager("Events"); |
IEvent updateEvent = eventsManager.GetEvent(new Guid(e.Appointment.ID.ToString())); |
updateEvent.ContentItem.SetMetaData("Title", e.ModifiedAppointment.Subject); |
updateEvent.ContentItem.SetMetaData("Event_Start", e.Appointment.Start); |
updateEvent.ContentItem.SetMetaData("Event_End", e.Appointment.End); |
eventsManager.Content.SaveContent(updateEvent.ContentItem, ContentStatus.Published); |
} |
#endregion |
#region Helper methods |
// getting the item url that will be used in EventsView control |
protected virtual string GetItemUrl(IContent contentItem, string singleItemUrl) |
{ |
string sep = String.Empty; |
string ret = String.Empty; |
string url = singleItemUrl; |
if (String.IsNullOrEmpty(url) && CmsContext.CurrentUrl != null) |
{ |
url = CmsContext.CurrentUrl.Path; |
} |
else |
{ |
sep = "&"; |
ret = String.IsNullOrEmpty(Context.Request.QueryString["ReturnURL"]) ? String.Concat("ReturnURL=", Context.Server.UrlEncode(Context.Request.RawUrl)) : String.Concat("ReturnURL=", Context.Server.UrlEncode(Context.Request.QueryString["ReturnURL"])); |
} |
if (String.IsNullOrEmpty(contentItem.Url)) |
{ |
if (url != null) |
{ |
int idx = url.IndexOf('?'); |
if (idx != -1) |
url = url.Substring(0, idx); |
} |
url = String.Concat(url, "?", |
ContentManager.ContentProviderKey, "=", contentItem.ProviderName, "&", |
ContentManager.ContentItemKey, "=", contentItem.ID, sep, ret); |
} |
else |
{ |
string itemUrl = String.Concat(contentItem.Url, eventsManager.Provider.ContentExtension); |
if (eventsManager.Provider.UrlFormatQueryStringIndex != -1) |
{ |
itemUrl += "?" + ContentUrlRewriterService.FormatURL(contentItem, eventsManager.Provider |
, ContentUrlRewriterService.FormatOptions.QueryString); |
} |
else if (sep.Length > 0) |
{ |
sep = "?"; |
} |
if (!itemUrl.StartsWith("~")) |
{ |
if (url != null) |
{ |
int idx = url.LastIndexOf('.'); |
if (idx != -1) |
{ |
url = url.Substring(0, idx); |
} |
else |
{ |
idx = url.IndexOf('?'); |
if (idx != -1) |
url = url.Substring(0, idx); |
} |
} |
itemUrl = String.Concat(VirtualPathUtility.RemoveTrailingSlash(url), itemUrl); |
} |
url = String.Concat(itemUrl, sep, ret); |
} |
IUrlService svc = UrlServices.GetLanguageService(); |
if (svc != null) |
return svc.ResolveLanguageUrl(url); |
return url; |
} |
#endregion |
#region Event handlers |
private void dataSource_Selecting(object sender, EventArgs e) |
{ |
((ObjectDataSourceView)sender).SelectParameters["from"] = new Parameter("from", TypeCode.DateTime, from.ToString()); |
((ObjectDataSourceView)sender).SelectParameters["to"] = new Parameter("to", TypeCode.DateTime, to.ToString()); |
} |
private void dataSource_ObjectCreating(object sender, ObjectDataSourceEventArgs e) |
{ |
e.ObjectInstance = eventsManager; |
} |
private void EventsSchedule_AppointmentCreated(object sender, AppointmentCreatedEventArgs e) |
{ |
var eventsManager = new EventsManager("Events"); |
IEvent _event = eventsManager.GetEvent(new Guid(e.Appointment.ID.ToString())); |
if (_event != null) |
{ |
HyperLink eventDetailsLink = (HyperLink)e.Container.FindControl("eventDetailsLink"); |
if (eventDetailsLink != null) |
{ |
eventDetailsLink.Text = e.Appointment.Subject; |
eventDetailsLink.ToolTip = _event.ContentItem.Content.ToString(); |
eventDetailsLink.NavigateUrl = GetItemUrl(_event.ContentItem, SingleEventUrl); |
} |
} |
} |
#endregion |
#region Private fields |
private string providerName; |
private EventsManager eventsManager; |
private ITemplate layoutTemplate; |
private EventsScheduleViewContainer container; |
private DateTime from = DateTime.MinValue; |
private DateTime to = DateTime.MaxValue; |
#endregion |
#region Templates |
private class DefaultTemplate : ITemplate |
{ |
public void InstantiateIn(Control container) |
{ |
} |
} |
#endregion |
#region Containers |
private class EventsScheduleViewContainer : GenericContainer<EventsScheduleViewCustom> |
{ |
public EventsScheduleViewContainer(EventsScheduleViewCustom owner) |
: base(owner) |
{ |
} |
public RadScheduler EventsSchedule |
{ |
get |
{ |
if (eventsSchedule == null) |
eventsSchedule = (RadScheduler)FindRequiredControl<Control>("eventsSchedule"); |
return eventsSchedule; |
} |
} |
private RadScheduler eventsSchedule; |
} |
#endregion |
} |