blazor-404547-components-scheduler-customization-custom-fields.md
The DevExpress Blazor Scheduler works with the DxSchedulerDataStorage object that contains source data for the following objects:
These items contain predefined sets of properties. When you bind a Scheduler to data, you map these properties to data source fields (see the AppointmentMappings, AppointmentLabelMappings, AppointmentStatusMappings, ResourceMappings properties).
You can add custom properties to Scheduler items:
You can use custom properties in appointment templates and custom appointment forms.
The following code snippet implements the following scenario:
Adds a custom field (Accepted) to an appointment’s source object.
Maps the field to the IsAccepted appointment property.
Uses the property value in VerticalAppointmentTemplate and HorizontalAppointmentTemplate (@context.CustomFields[...])).
<DxScheduler @ref="Scheduler"
@bind-StartDate="@StartDate" DataStorage="@DataStorage"
@bind-ActiveViewType="@ActiveViewType"
AppointmentFormShowing="OnAppointmentFormShowing"
ValidateEditForm="true" CssClass="demo-sc-size"
@bind-AppointmentFormMode="@AppointmentFormMode">
<Views>
<DxSchedulerWorkWeekView VisibleTime="@(new DxSchedulerTimeSpanRange(TimeSpan.FromHours(8), TimeSpan.FromHours(19)))">
<HorizontalAppointmentTemplate>
<div class="demo-sc-apt @(IsAccepted(context.CustomFields) ? "demo-sc-accepted " : "") w-100">
<div class="card demo-apt-bg dxbl-purple-color w-100"></div>
<div class="card shadow-sm p-1 demo-sc-apt-content text-white w-100">
@context.Appointment.Subject
</div>
</div>
</HorizontalAppointmentTemplate>
<VerticalAppointmentTemplate>
<div class="shadow-sm demo-sc-apt @(IsAccepted(context.CustomFields) ? "demo-sc-accepted" : "")">
<div class="card demo-apt-bg dxbl-purple-color"></div>
<div class="card demo-sc-apt-content text-white">
<div class="card demo-sc-status-container">
<div class="card demo-apt-status dxbl-purple-color"></div>
</div>
<div class="demo-apt-subject">
@context.Appointment.Subject
</div>
</div>
</div>
</VerticalAppointmentTemplate>
</DxSchedulerWorkWeekView>
</Views>
@* ... *@
</DxScheduler>
@* ... *@
@code {
DxScheduler Scheduler { get; set; }
SchedulerAppointmentFormMode AppointmentFormMode { get; set; } = SchedulerAppointmentFormMode.Both;
List<SchedulerAppointmentFormMode> EditModes = Enum.GetValues(typeof(SchedulerAppointmentFormMode))
.OfType<SchedulerAppointmentFormMode>()
.ToList();
DateTime StartDate { get; set; } = DateTime.Today;
SchedulerViewType ActiveViewType { get; set; } = SchedulerViewType.WorkWeek;
public class CustomAppointmentFormInfo : SchedulerAppointmentFormInfo {
public CustomAppointmentFormInfo(DxSchedulerAppointmentItem AppointmentItem, DxSchedulerDataStorage DataStorage, DxScheduler scheduler) : base(AppointmentItem, DataStorage, scheduler) { }
[Required]
public override string Subject {
get { return base.Subject; }
set { base.Subject = value; }
}
public bool IsAccepted {
get { return IsAccepted(CustomFields); }
set { CustomFields["IsAccepted"] = value; }
}
}
void OnAppointmentFormShowing(SchedulerAppointmentFormEventArgs args) {
args.FormInfo = new CustomAppointmentFormInfo(args.Appointment, DataStorage, Scheduler);
}
static bool IsAccepted(DxExpandoDictionaryObject customFields) => true == (bool?)customFields["IsAccepted"];
DxSchedulerDataStorage DataStorage = new DxSchedulerDataStorage() {
AppointmentsSource = AppointmentCollection.GetAppointments(),
AppointmentMappings = new DxSchedulerAppointmentMappings() {
Type = "AppointmentType",
Start = "StartDate",
End = "EndDate",
Subject = "Caption",
AllDay = "AllDay",
Location = "Location",
Description = "Description",
CustomFieldMappings = new List<DxSchedulerCustomFieldMapping> {
new DxSchedulerCustomFieldMapping { Name = "IsAccepted", Mapping = "Accepted" }
}
}
};
}
public static partial class Appointment {
public class Appointment {
public Appointment() { }
public int AppointmentType { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
//...
// Custom field
public bool Accepted { get; set; }
}
}
public static partial class AppointmentCollection {
public static List<Appointment> GetAppointments() {
DateTime date = DateTimeUtils.CreateWeekStart();
var dataSource = new List<Appointment>() {
new Appointment {
Caption = "Install New Router in Dev Room",
StartDate = date + (new TimeSpan(0, 10, 0, 0)),
EndDate = date + (new TimeSpan(0, 12, 30, 0)),
Label = 6,
Status = 4
},
new Appointment {
Caption = "Upgrade Personal Computers",
StartDate = date + (new TimeSpan(0, 13, 0, 0)),
EndDate = date + (new TimeSpan(0, 15, 30, 0)),
Label = 1,
Status = 4
},
new Appointment {
Caption = "Website Redesign Plan",
StartDate = date + (new TimeSpan(1, 9, 30, 0)),
EndDate = date + (new TimeSpan(1, 12, 0, 0)),
Label = 1,
Status = 1,
Accepted = true
},
new Appointment {
Caption = "New Brochures",
StartDate = date + (new TimeSpan(1, 13, 30, 0)),
EndDate = date + (new TimeSpan(1, 15, 15, 0)),
Label = 8,
Status = 2,
Accepted = true
},
// ...
};
return dataSource;
}
public static class DateTimeUtils {
public static DateTime GetWeekStart(DateTime date) {
return date.DayOfWeek == DayOfWeek.Sunday ? ValidWeekStart(date.Date) : ValidWeekStart(date.Date - CreateWeekOffset(date, DayOfWeek.Sunday));
}
public static DateTime GetBeginOfMonth(DateTime date) {
return new DateTime(date.Year, date.Month, 1);
}
static DateTime ValidWeekStart(DateTime date) {
TimeSpan weekSpan = new TimeSpan(7, 0, 0, 0);
DateTime baseDate = date.Date;
if(DateTime.MaxValue - date < weekSpan)
return baseDate - weekSpan;
return baseDate;
}
static TimeSpan CreateWeekOffset(DateTime date, DayOfWeek firstDayOfWeek) {
int offset = (date.DayOfWeek + 7 - firstDayOfWeek) % 7;
TimeSpan result = TimeSpan.FromDays(offset);
if(date.Ticks < result.Ticks)
result = TimeSpan.FromDays(offset - 7);
return result;
}
}
}
Run Demo: Scheduler - Custom Fields and Appointment Form
The following code snippet adds a custom field to LabelObject and maps this field to the appointment label’s custom property:
@code {
public class LabelObject {
public int Id { get; set; }
public string LabelName { get; set; }
public System.Drawing.Color LabelColor { get; set; }
public string MyCustomField { get; set; } // a custom field
}
DxSchedulerDataStorage DataStorage = new DxSchedulerDataStorage() {
AppointmentLabelsSource = new List<LabelObject>() {
new LabelObject() {
Id = 1,
LabelName = "Label One",
LabelColor = System.Drawing.Color.Aqua,
MyCustomField = "custom text for Label One"
},
new LabelObject() {
Id = 2,
LabelName = "Label Two",
LabelColor = System.Drawing.Color.Beige,
MyCustomField = "custom text for Label Two"
},
},
AppointmentLabelMappings = new DxSchedulerAppointmentLabelMappings() {
Id = "Id",
Caption = "LabelName",
Color = "LabelColor",
// Map the source object's custom field to the label's custom property
CustomFieldMappings = new List<DxSchedulerCustomFieldMapping> {
new DxSchedulerCustomFieldMapping { Name = "MyCustomProperty", Mapping = "MyCustomField" }
}
}
};
}
Refer to AppointmentLabelMappings for additional information.