Bind Blazor Scheduler to Data
- 7 minutes to read
The DevExpress Blazor Scheduler works with the DxSchedulerDataStorage object that contains source data for the following Scheduler persistent objects:
DxSchedulerDataStorage
maps data source fields to persistent object properties. This class also includes API that allows you to retrieve and manage persistent objects.
Common Steps
Follow the steps below to bind a Scheduler component to data:
- Create a DxSchedulerDataStorage object. Use the constructor without parameters.
- Use the DxSchedulerDataStorage.AppointmentsSource property to populate the storage with a collection of data objects.
- Create a DxSchedulerAppointmentMappings object and map data source fields to appointment properties.
- Assign the created
DxSchedulerAppointmentMappings
object to the DxSchedulerDataStorage.AppointmentMappings property. - Assign the data source to the Scheduler’s DataStorage property.
Bind to Runtime Data
You can bind the DevExpress Scheduler to data created at runtime. In this case, newly created appointments do not persist when you close the application. If you need to save changes, bind the Scheduler to a remote data source instead.
<DxScheduler StartDate="@DateTime.Today"
DataStorage="@DataStorage">
<DxSchedulerWeekView ShowWorkTimeOnly="true"></DxSchedulerWeekView>
</DxScheduler>
@code {
DxSchedulerDataStorage DataStorage = new DxSchedulerDataStorage() {
AppointmentsSource = AppointmentCollection.GetAppointments(),
AppointmentMappings = new DxSchedulerAppointmentMappings() {
Type = "AppointmentType",
Start = "StartDate",
End = "EndDate",
Subject = "Caption",
AllDay = "AllDay",
Location = "Location",
Description = "Description",
LabelId = "Label",
StatusId = "Status",
RecurrenceInfo = "Recurrence"
}
};
}
Bind to Remote Data
Bind to Data with Entity Framework Core
You can use Entity Framework Core in Blazor Server applications. Follow the steps below to bind the DevExpress Scheduler to data.
Fetch data from a database. See steps 1-6 in the following article:
Add a Scheduler to your application and bind it to data (refer to common steps).
- Handle Scheduler events to implement CRUD operations. Refer to the following topic for the list of available Scheduler events: Managing Appointments in Code.
The following code snippet does the following:
- Creates a DxSchedulerDataStorage object, sets its AppointmentsSource to
null
. - Assigns the created data storage object to the Scheduler’s DataStorage property.
- In the OnInitialized lifecycle method, creates a new DbContext and loads data from the DbContext to the DxSchedulerDataStorage.AppointmentsSource property.
Handles AppointmentInserted, AppointmentUpdated, and AppointmentRemoved events to implement CRUD operations in the Scheduler. To access a target appointment, the SourceObject property is used.
You can also use AppointmentInserting, AppointmentUpdating, and AppointmentRemoving events to implement CRUD operations. These events fire before modifications are applied to Scheduler’s appointment collection. You can access the database or service and validate that an appointment was in fact inserted/updated/removed. If validation is successful, pass the appointment further. If not, set the event argument’s Cancel property to
true
and display an error message (the service is unavailable or the appointment conflicts with another appointment in the database).Uses the DbContext.Dispose method to track the context for the component lifetime.
@inject IDbContextFactory<MedicsSchedulingContext> MedicsSchedulingContextFactory
@implements IDisposable
<DxScheduler StartDate="@startDate"
DataStorage="@DataStorage"
AppointmentUpdated="@AppointmentUpdated"
AppointmentInserted="@AppointmentInserted"
AppointmentRemoved="@AppointmentRemoved"
GroupType="SchedulerGroupType.Resource">
<DxSchedulerDayView DayCount="1" ShowWorkTimeOnly="true"></DxSchedulerDayView>
...
<Scales>
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Day" UnitCount="1"></DxSchedulerTimeScale>
<DxSchedulerTimeScale Unit="@SchedulerTimeScaleUnit.Hour" UnitCount="2"></DxSchedulerTimeScale>
</Scales>
</DxSchedulerTimelineView>
</DxScheduler>
@code {
DateTime startDate { get; set; } = new DateTime(2016, 10, 10);
MedicsSchedulingContext dbContext { get; set; }
DxSchedulerDataStorage DataStorage = new DxSchedulerDataStorage() {
AppointmentsSource = null,
AppointmentMappings = new DxSchedulerAppointmentMappings() {
Id = "Id",
Type = "EventType",
Start = "StartTime",
End = "EndTime",
Subject = "Subject",
AllDay = "AllDay",
Location = "Location",
Description = "Description",
LabelId = "Label",
StatusId = "Status",
ResourceId = "MedicId",
RecurrenceInfo = "RecurrenceInfo"
},
ResourcesSource = null,
ResourceMappings = new DxSchedulerResourceMappings() {
Id = "Id",
Caption = "DisplayName"
}
};
protected override void OnInitialized() {
dbContext = MedicsSchedulingContextFactory.CreateDbContext();
DataStorage.AppointmentsSource = dbContext.MedicalAppointments.ToList();
DataStorage.ResourcesSource = dbContext.Medics.ToList();
}
void AppointmentInserted(DxSchedulerAppointmentItem e) {
dbContext.Add(e.SourceObject);
dbContext.SaveChanges();
}
void AppointmentUpdated(DxSchedulerAppointmentItem e) {
dbContext.SaveChanges();
}
void AppointmentRemoved(DxSchedulerAppointmentItem e) {
dbContext.Remove(e.SourceObject);
dbContext.SaveChanges();
}
public void Dispose() {
dbContext?.Dispose();
}
}
Bind to a Web API Service
You can use a Web API service to bind the DevExpress Blazor Scheduler to remote data.
The following code snippet does the following:
- Creates a DxSchedulerDataStorage object, sets its AppointmentsSource to
null
. - Assigns the created data storage object to the Scheduler’s DataStorage property.
- In the OnInitializedAsync lifecycle method, defines the AppointmentsSource to populate the data storage with medical appointments (a Web API service is used).
Handles AppointmentInserting, AppointmentUpdating, and AppointmentRemoving events to implement CRUD operations in the Scheduler. These events fire before modifications are applied to Scheduler’s appointment collection. You can access a database or another service and validate that an appointment was inserted/updated/removed. If validation is successful, pass the appointment further. If not, set the event argument’s Cancel property to
true
and display an error message (the service is unavailable or the appointment conflicts with another appointment in the database).To access a target appointment or modify its properties from event handlers, use the Appointment property.
You can also use AppointmentInserted, AppointmentUpdated, and AppointmentRemoved events to implement CRUD operations. These events fire after modifications are applied to the Scheduler’s collection. Use these events if you do not need to validate data.
Refer to the following topic for the complete list of available Scheduler events: Managing Appointments in Code.
@inject HttpClient Http
@using System.Text.Json
@using System.Text.Json.Serialization
@using System.Text
<DxScheduler Id="schedulerWeekView"
StartDate="@startDate"
DataStorage="@DataStorage"
AppointmentInserting="AppointmentInserting"
AppointmentRemoving="AppointmentRemoving"
AppointmentUpdating="AppointmentUpdating">
<DxSchedulerDayView ShowWorkTimeOnly="true"></DxSchedulerDayView>
</DxScheduler>
@code {
protected DateTime startDate { get; set; } = new DateTime(2016, 10, 10);
DxSchedulerDataStorage DataStorage = new DxSchedulerDataStorage() {
AppointmentsSource = null,
AppointmentMappings = new DxSchedulerAppointmentMappings() {
Id = "id",
Type = "eventType",
Start = "startTime",
End = "endTime",
Subject = "subject",
AllDay = "allDay",
Location = "location",
Description = "description",
LabelId = "label",
StatusId = "status",
}
};
string fullWebAPIUrl = "https://localhost:44310/api/MedicalAppointments/";
protected override async Task OnInitializedAsync() {
var response = await Http.GetAsync(fullWebAPIUrl);
if (response.IsSuccessStatusCode) {
using var responseStream = await response.Content.ReadAsStreamAsync();
DataStorage.AppointmentsSource = await JsonSerializer.DeserializeAsync<IEnumerable<MedicalAppointments>>(responseStream);
}
}
async Task<HttpResponseMessage> PostItemAsync(MedicalAppointments item) {
var myContent = JsonSerializer.Serialize(item);
var response = await Http.PostAsync(fullWebAPIUrl, new StringContent(myContent, Encoding.Unicode, "application/json"));
return response;
}
async Task AppointmentInserting(SchedulerAppointmentOperationEventArgs e) {
MedicalAppointments insertedItem = e.Appointment.SourceObject as MedicalAppointments;
HttpResponseMessage response = await PostItemAsync(insertedItem);
if(response.IsSuccessStatusCode) {
using var responseStream = await response.Content.ReadAsStreamAsync();
MedicalAppointments newItem = await JsonSerializer.DeserializeAsync<MedicalAppointments>(responseStream);
insertedItem.id = newItem.id;
}
else
e.Cancel = true;
}
async Task AppointmentUpdating(SchedulerAppointmentOperationEventArgs e) {
MedicalAppointments updatedItem = e.Appointment.SourceObject as MedicalAppointments;
var myContent = JsonSerializer.Serialize(updatedItem);
var request = new HttpRequestMessage(HttpMethod.Put, fullWebAPIUrl + Convert.ToInt32(updatedItem.id));
request.Content = new StringContent(myContent, Encoding.Unicode, "application/json");
var response = await Http.SendAsync(request);
if(!response.IsSuccessStatusCode)
e.Cancel = true;
}
async Task AppointmentRemoving(SchedulerAppointmentOperationEventArgs e) {
var response = await Http.DeleteAsync(fullWebAPIUrl + e.Appointment.Id);
if (!response.IsSuccessStatusCode)
e.Cancel = true;
}
}