---
title: "Easily Load Appointments in .NET MAUI Scheduler with SQLite and Perform CRUD"
published_at: "2024-02-01T12:18:18+00:00"
modified_at: "2025-11-06T12:31:12+00:00"
url: "https://www.syncfusion.com/blogs/post/load-maui-scheduler-sqlite-crud"
excerpt: "Let’s see how to load appointments in the .NET MAUI Scheduler with the SQLite database and perform CRUD actions on it."
taxonomy_category:
  - ".NET MAUI"
  - "Desktop"
  - "Development"
  - "Mobile"
  - "Scheduler"
  - "UI"
taxonomy_post_tag:
  - ".NET MAUI"
  - "CRUD"
  - "MAUI"
  - "Mobile"
  - "Scheduler"
  - "SQL"
---

# Easily Load Appointments in .NET MAUI Scheduler with SQLite and Perform CRUD

[Jeyasri Murugan](https://www.syncfusion.com/blogs/author/jeyasrim)

![Easily Load Appointments in .NET MAUI Scheduler with SQLite and Perform CRUD](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/Easily-Load-Appointments-in-.NET-MAUI-Scheduler-with-SQLite-and-Perform-CRUD.jpg)


In this blog, we’ll see how to load appointments in the .NET MAUI Scheduler with the SQLite database, perform CRUD actions (create, read, update, and delete) on the SQLite database, and dynamically update the changes in the .NET MAUI Scheduler.

The Syncfusion [.NET MAUI Scheduler](https://www.syncfusion.com/maui-controls/maui-scheduler)
 is a powerful tool that provides a wide range of scheduling functionalities, allowing for the efficient management of appointments.

[SQLite](https://en.wikipedia.org/wiki/SQLite)
 is a lightweight, open-source, and self-contained relational database management system (RDBMS). It is popular for embedded systems, mobile apps, and desktop software due to its ease of use and efficiency. It seamlessly integrates with .NET MAUI apps to load and save data objects in shared code.

## Agenda:

- [Create SQLite connection, define model, and populate appointments.](#SQLiteconnection)
- [Build a schedule appointment editor.](#ScheduleAppointment)
- [Perform CRUD operations on SQLite database and update .NET MAUI Scheduler.](#PerformCRUD)

Let’s get started!

**Note:** Before proceeding, see the [getting started with .NET MAUI Scheduler documentation](https://help.syncfusion.com/maui/scheduler/getting-started)
.


## Create SQLite connection, define model, and populate appointments

Let’s explore the simple steps to connect SQLite with the Syncfusion .NET MAUI Scheduler.

### Step 1: Install the required package

First, we are going to install the **sqlite-net-pcl** package to connect the SQLite database.

Refer to the following image.

![Install sqlite-net-pcl NuGet package](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/sqlite-net-pcl-NuGet-Package.png)

### Step 2: Create the SQLite connection

Next, define the SQLite connection using the **SQLiteConnection** API and set up the database path property in the** SchedulerDatabase.cs**file.

```
readonly SQLiteConnection _database;

 public SchedulerDatabase(string dbPath)
 {
     _database = new SQLiteConnection(dbPath);
 }
```

Now, create an instance for the **SQLite connection** with the database ** Path** property and initialize it in the ** App.Xaml.cs** file to use the database.

Refer to the following code example.

```
public static SchedulerDatabase Database
{
    get
    {
        if (database == null)
        {
            database = new SchedulerDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "MAUISchedulerDatabase.db3"));
        }
        return database;
    }
}
```

### Step 3: Define the database table model

Then, create a model class named Appointment to hold the property values from the database table in the **Appointment.cs** file.

```
public class Appointment
{
      [PrimaryKey, AutoIncrement, Unique]
      public int ID { get; set; }
      public DateTime From { get; set; }
      public DateTime To { get; set; }
      public bool AllDay { get; set; }
      public string EventName { get; set; }
      public string Notes { get; set; }
}
```

Subsequently, create a table named **Appointment** in that SQLite database.

**SchedulerDatabase.cs**

```
_database.CreateTable<Appointment>();
```

### Step 4: Populate SQLite database appointments

In the **SchedulerViewModel** class, populate the data from the SQLite database.

```
public ObservableCollection<SchedulerAppointment> Appointments { get; set; }

var dataBaseAppointments = App.Database.GetSchedulerAppointment();
if (dataBaseAppointments != null && dataBaseAppointments.Count > 0)
{
    foreach (Appointment appointment in dataBaseAppointments)
    {
        Appointments.Add(new SchedulerAppointment()
        {
            StartTime = appointment.From,
            EndTime = appointment.To,
            Subject = appointment.EventName,
            IsAllDay = appointment.AllDay,
            Id = appointment.ID
        });
    }
}
```

Then, retrieve the appointments from the SQLite database in the SchedulerDatabase.cs file.

```
public List<Appointment> GetSchedulerAppointment()
{
    return _database.Table<Appointment>().ToList();
}
```

### Step 5: Bind appointments to the Scheduler

Initialize the .NET MAUI Scheduler control and bind its **AppointmentsSource** property to the ** Appointments** property of the ** SchedulerViewModel** class.

**MainPage.xaml**

```
xmlns:scheduler="clr-namespace:Syncfusion.Maui.Scheduler;assembly=Syncfusion.Maui.Scheduler"

<ContentPage.BindingContext>
    <local:SchedulerViewModel/>
</ContentPage.BindingContext>

<scheduler:SfScheduler x:Name="Scheduler"
                       View="Week"
                       Tapped="Scheduler_Tapped"
                       AppointmentsSource="{Binding Appointments}"
                       ShowWeekNumber="True"
                       AllowedViews="Day,Week,WorkWeek,Agenda,Month,TimelineDay,TimelineWeek,TimelineWorkWeek,TimelineMonth">
</scheduler:SfScheduler>
```

After executing the previous code examples, we’ll get output like in the following image.

![Populating appointments from SQLite database to .NET MAUI Scheduler](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/Populating-appointments-from-SQLite-database-to-.NET-MAUI-Scheduler.jpg)

Populating appointments from SQLite database to .NET MAUI Scheduler


## Build a schedule appointment editor

Create an appointment editor that enables the addition, saving, and deletion of appointments in the .NET MAUI Scheduler.

Refer to the following code example to create a model class to store the basic details of the appointment editor in the AppointmentEditorModel.cs file.

```
public class AppointmentEditorModel : INotifyPropertyChanged
{
        private string subject , notes;
        private TimeSpan startTime , endTime;
        private bool isAllDay , isEditorEnabled= true;
        private DateTime startDate, endDate;

        public string Subject
        {
            get { return subject; }
            set
            {
                subject = value;
                RaisePropertyChanged(nameof(this.Subject));
            }
        }

        public string Notes
        {
            get { return notes; }
            set
            {
                notes = value;
                RaisePropertyChanged(nameof(this.Notes));
            }
        }

        public TimeSpan StartTime
        {
            get { return startTime; }
            set
            {
                startTime = value;
                RaisePropertyChanged(nameof(this.StartTime));
            }
        }

        public TimeSpan EndTime
        {
            get { return endTime; }
            set 
            {
                endTime = value;
                RaisePropertyChanged(nameof(this.EndTime));
            }
        }

        public bool IsAllDay
        {
            get { return isAllDay; }
            set
            {
                isAllDay = value;
                RaisePropertyChanged(nameof(this.IsAllDay));
            }
        }

        public DateTime StartDate
        {
            get { return startDate; }
            set
            {
                startDate = value; 
                RaisePropertyChanged(nameof(this.StartDate));
            }
        }

        public DateTime EndDate
        {
            get { return endDate; }
            set 
            {
                endDate = value;
                RaisePropertyChanged(nameof(this.EndDate));
            }
        }

        public bool IsEditorEnabled
        {
            get { return isEditorEnabled; }
            set 
            {
                isEditorEnabled = value;
                RaisePropertyChanged(nameof(this.IsEditorEnabled));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }
}
```

Now, let’s create the appointment editor using the.NET MAUI [Popup](https://help.syncfusion.com/maui/popup/getting-started)
 and [Text Input Layout](https://help.syncfusion.com/maui/textinputlayout/getting-started)
 controls. Ensure that the **AppointmentEditorModel** property is correctly bound in each appointment editor, allowing seamless two-way value updates between the appointment and the editor.

**MainPage.xaml**

```
xmlns:inputLayout="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
xmlns:popup="clr-namespace:Syncfusion.Maui.Popup;assembly=Syncfusion.Maui.Popup"

<ContentPage.BindingContext>
    <local:SchedulerViewModel/>
</ContentPage.BindingContext>

<popup:SfPopup x:Name="sfPopup" IsOpen="{Binding IsOpen}" BindingContext="{Binding}" WidthRequest="550" HeightRequest="500" AutoSizeMode="Both" ShowHeader="False" ShowFooter="False">
    <popup:SfPopup.ContentTemplate>
        <DataTemplate>
            <Grid RowDefinitions="*,auto" Margin="20">
                <ScrollView>
                    <StackLayout>
                        <inputLayout:SfTextInputLayout x:Name="eventName_layout" Hint="Event name" ContainerBackground="Transparent" OutlineCornerRadius="8" ContainerType="Outlined">
                            <Entry x:Name="eventNameText" Text="{Binding AppointmentEditorModel.Subject}" />
                        </inputLayout:SfTextInputLayout>

                        <Grid ColumnDefinitions="0.5*,0.5*">
                            <inputLayout:SfTextInputLayout Hint="Start date" OutlineCornerRadius="8" ContainerBackground="Transparent" ContainerType="Outlined">
                                <DatePicker x:Name="startDate_picker" Date="{Binding AppointmentEditorModel.StartDate}" />
                            </inputLayout:SfTextInputLayout>

                            <inputLayout:SfTextInputLayout Grid.Column="1" Margin="10,0,0,0" Hint="Start time" OutlineCornerRadius="8" ContainerBackground="Transparent" ContainerType="Outlined">
                                <TimePicker x:Name="startTime_picker" IsEnabled="{Binding AppointmentEditorModel.IsEditorEnabled}" VerticalOptions="Start" Time="{Binding AppointmentEditorModel.StartTime, Mode=TwoWay}" />
                            </inputLayout:SfTextInputLayout>
                        </Grid>

                        <Grid ColumnDefinitions="0.5*,0.5*">
                            <inputLayout:SfTextInputLayout Hint="End date" OutlineCornerRadius="8" ContainerBackground="Transparent" ContainerType="Outlined">
                                <DatePicker x:Name="endDate_picker" Date="{Binding AppointmentEditorModel.EndDate}" />
                            </inputLayout:SfTextInputLayout>

                            <inputLayout:SfTextInputLayout Hint="End time" Margin="10,0,0,0" Grid.Column="1" OutlineCornerRadius="8" ContainerBackground="Transparent" ContainerType="Outlined">
                                <TimePicker x:Name="endTime_picker" IsEnabled="{Binding AppointmentEditorModel.IsEditorEnabled}" HorizontalOptions="Start" Time="{Binding AppointmentEditorModel.EndTime}" />
                            </inputLayout:SfTextInputLayout>
                        </Grid>

                        <Grid Margin="2,-12,0,0" x:Name="allDay" VerticalOptions="Start" ColumnDefinitions="50,*">
                            <Label Grid.Column="0" VerticalTextAlignment="Center" Text="AllDay"/>
                            <Switch Toggled="SwitchAllDay_Toggled" IsToggled="{Binding AppointmentEditorModel.IsAllDay}" Margin="10,0,0,0" x:Name="switchAllDay" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" />
                        </Grid>

                        <inputLayout:SfTextInputLayout x:Name="organizer_layout" Hint="Notes" OutlineCornerRadius="8" ContainerBackground="Transparent" ContainerType="Outlined">
                            <Editor x:Name="organizerText" Text="{Binding AppointmentEditorModel.Notes}" />
                        </inputLayout:SfTextInputLayout>
                    </StackLayout>
                </ScrollView>

                <Grid HeightRequest="40" Grid.Row="1" ColumnDefinitions="*,auto">
                    <Button x:Name="DeleteButton" Command="{Binding DeleteAppointment}" WidthRequest="80" Text="Delete" HorizontalOptions="Start" />

                    <HorizontalStackLayout HorizontalOptions="End" Grid.Column="1">
                        <Button x:Name="cancelButton" WidthRequest="80" Text="Cancel" Command="{Binding CancelEditAppointment}" />
                        <Button Margin="10,0,0,0" x:Name="saveButton" Command="{Binding AddAppointment}" Text="Save" WidthRequest="80" TextColor="White" />
                    </HorizontalStackLayout>
                </Grid>
            </Grid>
        </DataTemplate>
    </popup:SfPopup.ContentTemplate>
</popup:SfPopup>
```

Refer to the following code example to initialize the **AppointmentEditorModel** in the ** SchedulerViewModel.cs** file.

```
public AppointmentEditorModel AppointmentEditorModel { get; set; }

this.AppointmentEditorModel = new AppointmentEditorModel();

private bool isOpen;
public bool IsOpen
{
    get { return isOpen; }
    set
    {
        isOpen = value;
        OnPropertyChanged(nameof(this.IsOpen));
    }
}
```

The appointment editor pop-up will be displayed upon tapping the scheduler, providing the options to add, edit, or delete the appointments. Refer to the following code examples.

**MainPage.xaml.cs**

```
private void Scheduler_Tapped(object sender, SchedulerTappedEventArgs e)
{
    if (this.BindingContext is SchedulerViewModel schedulerViewModel)
    {
        SchedulerAppointment appointment;
        DateTime selectedDate;

        if (e.Appointments != null && e.Appointments.Count > 0)
        {
            appointment = (SchedulerAppointment)e.Appointments[0];
            selectedDate = appointment.StartTime;
        }
        else
        {
            appointment = null;
            selectedDate = (DateTime)e.Date;
        }
        schedulerViewModel.UpdateEditor(appointment, selectedDate);
        sfPopup.Show();
    }
}
```

**SchedulerViewModel.cs**

```
private SchedulerAppointment appointment;
private DateTime selectedDate;

internal void UpdateEditor(SchedulerAppointment appointment, DateTime selectedDate)
{
    this.appointment = appointment;
    this.selectedDate = selectedDate;

    if (this.appointment != null)
    {
        AppointmentEditorModel.Subject = this.appointment.Subject;
        AppointmentEditorModel.Notes = this.appointment.Notes;
        AppointmentEditorModel.StartDate = this.appointment.StartTime;
        AppointmentEditorModel.EndDate = this.appointment.EndTime;
        AppointmentEditorModel.IsEditorEnabled = true;

        if (!this.appointment.IsAllDay)
        {
            AppointmentEditorModel.StartTime = new TimeSpan(this.appointment.StartTime.Hour, this.appointment.StartTime.Minute, this.appointment.StartTime.Second);
            AppointmentEditorModel.EndTime = new TimeSpan(this.appointment.EndTime.Hour, this.appointment.EndTime.Minute, this.appointment.EndTime.Second);
            AppointmentEditorModel.IsAllDay = false;
            AppointmentEditorModel.IsEditorEnabled = true;
        }
        else
        {
            AppointmentEditorModel.StartTime = new TimeSpan(12, 0, 0);
            AppointmentEditorModel.EndTime = new TimeSpan(12, 0, 0);
            AppointmentEditorModel.IsEditorEnabled = false;
            AppointmentEditorModel.IsAllDay = true;
        }
    }
    else
    {
        AppointmentEditorModel.Subject = "";
        AppointmentEditorModel.Notes = "";
        AppointmentEditorModel.IsAllDay = false;
        AppointmentEditorModel.StartDate = this.selectedDate;
        AppointmentEditorModel.StartTime = new TimeSpan(this.selectedDate.Hour, this.selectedDate.Minute, this.selectedDate.Second);
        AppointmentEditorModel.EndDate = this.selectedDate;
        AppointmentEditorModel.EndTime = new TimeSpan(this.selectedDate.Hour + 1, this.selectedDate.Minute, this.selectedDate.Second);
    }
}
```

After executing the previous code examples, we’ll get an output like in the following image.

![Schedule appointment editor](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/Schedule-appointment-editor.jpg)

Schedule appointment editor


## Perform CRUD operations on SQLite database and update the .NET MAUI Scheduler

Let’s see how to perform CRUD actions on the SQLite database while synchronizing the changes with the .NET MAUI Scheduler control.

When you tap on the Scheduler, you can utilize the appointment editor pop-up to add, edit, and delete appointment details. On clicking the **Save** or ** Delete** buttons in the appointment editor, both the Scheduler and SQLite database will be updated.

### Saving an appointment

You can add appointments by providing the required details and clicking the **Save** button in the appointment editor. The following code examples illustrates the command associated with the ** Save** button.

**SchedulerViewModel.cs**

```
public Command AddAppointment { get; set; }

AddAppointment = new Command(AddAppointmentDetails);

private void AddAppointmentDetails()
{
    var endDate = AppointmentEditorModel.EndDate;
    var startDate = AppointmentEditorModel.StartDate;
    var endTime = AppointmentEditorModel.EndTime;
    var startTime = AppointmentEditorModel.StartTime;

    if (endDate < startDate)
    {
        Application.Current.MainPage.DisplayAlert("", "End date should be greater than start date", "OK");
    }
    else if (endDate == startDate)
    {
        if (endTime <= startTime)
        {
            Application.Current.MainPage.DisplayAlert("", "End time should be greater than start time", "OK");
        }
        else
        {
            AppointmentDetails();
        }
    }
    else
    {
        AppointmentDetails();
    }
}

private void AppointmentDetails()
{
    if (appointment == null)
    {
        appointment = new SchedulerAppointment();
        appointment.Subject = AppointmentEditorModel.Subject;
        appointment.StartTime = AppointmentEditorModel.StartDate.Date.Add(AppointmentEditorModel.StartTime);
        appointment.EndTime = AppointmentEditorModel.EndDate.Date.Add(AppointmentEditorModel.EndTime);
        appointment.IsAllDay = AppointmentEditorModel.IsAllDay;
        appointment.Notes = AppointmentEditorModel.Notes;

        if (this.Appointments == null)
        {
            this.Appointments = new ObservableCollection<SchedulerAppointment>();
        }

        appointment.Id = Appointments.Count;
        //// Add the appointments in the Scheduler.
        Appointments.Add(appointment);
    }
    else
    {
        appointment.Subject = AppointmentEditorModel.Subject;
        appointment.StartTime = AppointmentEditorModel.StartDate.Date.Add(AppointmentEditorModel.StartTime);
        appointment.EndTime = AppointmentEditorModel.EndDate.Date.Add(AppointmentEditorModel.EndTime);
        appointment.IsAllDay = AppointmentEditorModel.IsAllDay;
        appointment.Notes = AppointmentEditorModel.Notes;
    }

    SaveSchedulerAppointmentAsync();

    this.IsOpen = false;
}
```

The appointment details will be updated based on the user input, and the **SaveSchedulerAppointmentAsync()** method handles the addition or editing of appointments in both the Scheduler and the SQLite database.

Refer to the following code examples for saving an appointment in the SQLite database.

**SchedulerViewModel.cs**

```
private void SaveSchedulerAppointmentAsync()
{
    //// - add or edit the appointment in the database collection.
    var editAppointment = new Appointment()
    {
        From = appointment.StartTime,
        To = appointment.EndTime,
        AllDay = appointment.IsAllDay,
        Notes = appointment.Notes,
        EventName = appointment.Subject,
        ID = (int)appointment.Id
    };
    App.Database.SaveSchedulerAppointmentAsync(editAppointment);
}
```

**SchedulerDatabase.cs**

```
//Insert an appointment in the database.
 public int SaveSchedulerAppointmentAsync(Appointment appointment)
 {
     if (appointment == null)
     {
         throw new Exception("Null");
     }

     return _database.InsertOrReplace(appointment);
 }
```

### Deleting an appointment

By clicking the **Delete** button, we can delete an appointment in the .NET MAUI Scheduler and in the SQLite database. The following code examples demonstrate the command associated with the ** Delete** button.

**SchedulerViewModel.cs**

```
public Command DeleteAppointment { get; set; }

DeleteAppointment = new Command(DeleteSchedulerAppointment);

private void DeleteSchedulerAppointment()
{
    if (appointment == null)
    {
        this.IsOpen = false;
        return;
    }

    //// Remove the appointments in the Scheduler.
    Appointments.Remove(this.appointment);
    //// Delete appointment in the database.
    var deleteAppointment = new Appointment()
    {
        From = appointment.StartTime,
        To = appointment.EndTime,
        AllDay = appointment.IsAllDay,
        Notes = appointment.Notes,
        EventName = appointment.Subject,
        ID = (int)appointment.Id
    };

    App.Database.DeleteSchedulerAppointmentAsync(deleteAppointment);
    this.IsOpen = false;
}
```

**SchedulerDatabase.cs**

```
//Delete an appointment in the database.
public int DeleteSchedulerAppointmentAsync(Appointment appointment)
{
      return _database.Delete(appointment);
}
```

After executing the previous code examples, we’ll get output like in the following image.

![Performing CRUD operations in SQLite database using .NET MAUI Scheduler](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/Performing-CRUD-operations-in-SQLite-database-using-.NET-MAUI-Scheduler-test.gif)

Performing CRUD operations in SQLite database using .NET MAUI Scheduler

When rerunning the app, the .NET MAUI Scheduler will fetch the updated appointments from the SQLite database, and the output will be as follows.

![Updating the .NET MAUI Scheduler appointments loaded from SQLite database](https://www.syncfusion.com/blogs/wp-content/uploads/2024/02/Updating-the-.NET-MAUI-Scheduler-appointments-loaded-from-SQLite-database.jpg)

Updating the .NET MAUI Scheduler appointments loaded from SQLite database

## GitHub reference

For more details, refer to the complete project on the [GitHub repository](https://github.com/SyncfusionExamples/Loading-Appointments-in-.NET-MAUI-Scheduler-with-SQLite-and-Performing-CRUD-operations)
.


## Conclusion

Thanks for reading! In this blog, we learned how to load appointments in the [.NET MAUI Scheduler](https://www.syncfusion.com/maui-controls/maui-scheduler)
 with SQLite and perform effortless CRUD operations. Try out the steps discussed in this blog post and leave your feedback in the comments section below!

The newest version of Essential Studio® is available for existing customers on the [License and Downloads](https://www.syncfusion.com/account/login)
 page. If you’re not a Syncfusion customer, sign up for our [30-day free trial](https://www.syncfusion.com/downloads)
 to explore our features.

For questions, you can contact us through our [support forum](https://www.syncfusion.com/forums)
, [support portal](https://support.syncfusion.com/)
, or [feedback portal](https://www.syncfusion.com/feedback/maui)
. We are always happy to assist you!

## Related blogs

- [Chart of the Week: Create a .NET MAUI Stacked Column Chart for the Top-Earning Female Athletes](https://www.syncfusion.com/blogs/post/maui-stackedcolumn-chart-athlete.aspx)
- [Syncfusion .NET MAUI 2024 Road Map](https://www.syncfusion.com/blogs/post/dotnet-maui-2024-road-map.aspx)
- [Chart of the Week: Creating a .NET MAUI Bar Chart to Visualize Type 1 Diabetes Prevalence](https://www.syncfusion.com/blogs/post/dotnet-maui-bar-chart-diabetes.aspx)
- [Introducing the New .NET MAUI PullToRefresh Control](https://www.syncfusion.com/blogs/post/dotnet-maui-pull-to-refresh.aspx)
