Custom Edit Form

This demo illustrates how to change the Bootstrap Scheduler control UI. You can access the customization options for various dialogs using the OptionsDialogs property. In this demo, the OptionsDialogs.AppointmentDialog is used to customize the Edit Appointment form.

Create a new appointment or right-click on any existing appointment and choose the Open item, to see a custom Edit Appointment form in place of the standard form. This form not only allows you to edit standard appointment properties, but also the ones obtained via custom mappings.

Note that data field mappings should be specified before the GenerateDefaultLayoutElements method is called since only mapped appointment fields are generated by default.

 

<dx:BootstrapScheduler ID = "SchedulerCustomEditForm" runat="server"
    AppointmentDataSourceID="AppointmentDataSource" ResourceDataSourceID="efResourceDataSource"
    ActiveViewType="WorkWeek" GroupType="Resource">
    <OptionsResourceNavigator EnableIncreaseDecrease="false" />
    <Storage>
        <Resources>
            <CustomFieldMappings>
                <dx:ASPxResourceCustomFieldMapping Name="Phone" Member="Phone" />
                <dx:ASPxResourceCustomFieldMapping Name="Photo" Member="PhotoBytes" />
            </CustomFieldMappings>
        </Resources>
    </Storage>
    <Views>
        <DayView ResourcesPerPage="2" DayCount="2" />
        <WorkWeekView ResourcesPerPage="1" />
        <FullWeekView Enabled="true" ResourcesPerPage="1"/>
        <WeekView Enabled="false"/>
        <MonthView ResourcesPerPage="1" />
        <TimelineView ResourcesPerPage="2" />
    </Views>
</dx:BootstrapScheduler>
protected void Page_Init(object sender, EventArgs e) {
    var dialog = SchedulerCustomEditForm.OptionsDialogs.AppointmentDialog.UseViewModel(() => new DevExpress.Web.Demos.Bootstrap.CustomAppointmentEditDialogViewModel(SchedulerCustomEditForm));
    SchedulerDataHelper.SetupDefaultMappings(SchedulerCustomEditForm);
    dialog.GenerateDefaultLayoutElements();
    var resourceContainerGroup = dialog.LayoutElements.CreateGroup("resourceContainer", (g) => {
        g.ColSpanXl = 12;
        g.LayoutElements.CreateGroup("resourceGroup", (resourceGroup) => {
            var resourceIds = dialog.FindLayoutElement("ResourceIds");
            resourceIds.ColSpanXl = 12;
            resourceGroup.ColSpanXl = 6;
            resourceGroup.LayoutElements.Add(resourceIds);
        });
        g.LayoutElements.CreateGroup("resourceDetailGroup", (detailGroup) => {
            detailGroup.ColSpanXl = 6;
            detailGroup.LayoutElements.CreateField(m => m.Phone).ColSpanXl = 12;
            detailGroup.LayoutElements.CreateField(m => m.Photo).ColSpanXl = 12;
        });
    });
    dialog.InsertAfter(resourceContainerGroup, dialog.FindLayoutElement("StatusKey"));
}

Custom Appointments

This demo illustrates how to customize appointments' appearance. In this demo, the InitAppointmentDisplayText event is handled to apply custom formating to appointments' displayed texts. Additionally, the InitAppointmentImages event is used to display custom images based on appointment properties.

 

<dx:BootstrapScheduler ID="SchedulerCustomAppointments" ClientInstanceName="schedulerCustomAppointments"
    runat="server" ActiveViewType="WorkWeek" GroupType="Resource"
    OnInitAppointmentDisplayText="SchedulerCustomAppointments_InitAppointmentDisplayText"
    OnInitAppointmentImages="SchedulerCustomAppointments_InitAppointmentImages"
    AppointmentDataSourceID="AppointmentDataSource" ResourceDataSourceID="efResourceDataSource">
    <OptionsResourceNavigator EnableIncreaseDecrease="false" />
    <Views>
        <DayView ResourcesPerPage="2" DayCount="2" />
        <WorkWeekView ResourcesPerPage="1" />
        <FullWeekView Enabled="true" ResourcesPerPage="1" />
        <WeekView Enabled="false" />
        <MonthView ResourcesPerPage="1" />
        <TimelineView ResourcesPerPage="2" />
    </Views>
</dx:BootstrapScheduler>
protected void SchedulerCustomAppointments_InitAppointmentDisplayText(object sender, AppointmentDisplayTextEventArgs e) {
    Appointment apt = e.Appointment;
    e.Text = String.Format("[{0}] {1}", apt.Location, apt.Subject);
    e.Description = String.Format("Details: {0}", apt.Description);
}
protected void SchedulerCustomAppointments_InitAppointmentImages(object sender, DevExpress.Web.ASPxScheduler.AppointmentImagesEventArgs e) {
    Appointment apt = e.Appointment;
    AppointmentImageInfoCollection c = e.ImageInfoList;
    c.Clear();
    c.Images = CustomAppointmentsHelper.CustomImages;
    if(e.Appointment.IsRecurring)
        CustomAppointmentsHelper.AddRecurrentAppointmentImages(c, e.Appointment.IsException);
    else
        CustomAppointmentsHelper.AddNotRecurrentAppointmentImages(c);
}

Custom Context Menu

This demo illustrates how to customize a popup menu - a menu, invoked by right-clicking the Scheduler control or via the smart tag.

In this example, default scheduler menu items are replaced with custom ones. Instead of commands that enable you to create a new appointment or change its label and status, the popup menu contains submenu items that allow the creation of predefined events.

To achieve this, handle the PopupMenuShowing event. It provides access to a BootstrapSchedulerPopupMenu class instance, which represents the popup menu being displayed, and contains methods for modifying menu items and structure.

 

<dx:BootstrapScheduler ID="SchedulerCustomContextMenu" runat="server" GroupType="Resource" ActiveViewType="WorkWeek"
    OnPopupMenuShowing="SchedulerCustomContextMenu_PopupMenuShowing"
    OnCustomCallback="SchedulerCustomContextMenu_CustomCallback"
    AppointmentDataSourceID="AppointmentDataSource" ResourceDataSourceID="efResourceDataSource">
    <ClientSideEvents MenuItemClicked="OnMenuItemClicked" />
    <OptionsResourceNavigator EnableIncreaseDecrease="false" />
    <Views>
        <DayView ResourcesPerPage="2" DayCount="2" />
        <WorkWeekView ResourcesPerPage="1" />
        <FullWeekView Enabled="true" ResourcesPerPage="1" />
        <WeekView Enabled="false" />
        <MonthView Enabled="false" />
        <TimelineView ResourcesPerPage="2" />
    </Views>
</dx:BootstrapScheduler>
protected void SchedulerCustomContextMenu_PopupMenuShowing(object sender, BootstrapSchedulerPopupMenuShowingEventArgs e) {
    var menu = e.Menu;
    var menuItems = menu.Items;
    if(menu.MenuId.Equals(SchedulerMenuItemId.DefaultMenu)) {
        CustomMenuHelper.ClearUnusedDefaultMenuItems(menu);
        CustomMenuHelper.AddScheduleNewEventSubMenu(menu, "Schedule New Event", "NewEvent");
    }
    else if(menu.MenuId.Equals(SchedulerMenuItemId.AppointmentMenu)) {
        menu.Items.Clear();
        CustomMenuHelper.AddScheduleNewEventSubMenu(menu, "Change Event", "ChangeEvent");
        var deleteItem = new BootstrapMenuItem("Delete", "CustomItem_Delete");
        deleteItem.BeginGroup = true;
        menuItems.Add(deleteItem);
    }
}
protected void SchedulerCustomContextMenu_CustomCallback(object sender, CallbackEventArgsBase e) {
    var scheduler = (BootstrapScheduler)sender;
    string[] callbackParams = e.Parameter.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
    var command = callbackParams[0];
    var label = (CustomLabel)Enum.Parse(typeof(CustomLabel), callbackParams[1]);
    if(command == "ChangeEvent") {
        Appointment apt = scheduler.SelectedAppointments[0];
        CustomMenuHelper.UpdateAppointment(label, apt);
    }
    else if(command == "NewEvent")
        CustomMenuHelper.CreateAppointment(label, scheduler);
}
function OnMenuItemClicked(s, e) {
    var menuParameters = e.itemName.split("_");
    if (menuParameters[0] === "CustomItem") {
        e.handled = true;
        if (menuParameters[1] === "Delete" && confirm("Delete this appointment?")) {
            var selectedAppointment = s.GetAppointmentById(s.GetSelectedAppointmentIds()[0]);
            s.DeleteAppointment(selectedAppointment);
        }
        if (menuParameters.length > 2)
            s.PerformCallback(menuParameters[1] + "_" + menuParameters[2]);
    }
}
Screen Size
Color Themes
Demo QR Code