52 Weeks of Xamarin: Week 13 – Writing It Thrice

In this and a number of following posts, I’ll build the same program three times: once in Xamarin.Forms, once in iOS and once in Android.  ToDoListForms

This is directly based on my Pluralsight course, Beginning Mobile Development with Xamarin

To get started, we’ll go through the Xamarin.Forms application fairly quickly as this series has already covered a lot of material on writing Xamarin.Forms applications.   Let’s begin by creating our model class: ToDoItem

We know we want to save the data to a SQLite database, so we’ll add an ID field and the necessary attributes:

 using System;
 using SQLite;
 
 namespace ToDo {
     public class ToDoItem {
 
         [PrimaryKeyAttribute, AutoIncrement]
         public int ID { get; set; }
 
         public string TaskName { get; set; }
 
         public string Priority { get; set; }
 
         public DateTime DueDate { get; set; }
 
         public bool IsDeleted { get; set; }
 
     }
 }

Create Page

We start by creating our first page, CreateToDo, and its associated file CreateToDoViewModel.  CreateToDo.xaml provides the UI, which includes the buttons Save, Cancel and Review.  Here is the complete XAML page,

 <?xml version="1.0" encoding="UTF-8"?>
 <ContentPage
   xmlns="http://xamarin.com/schemas/2014/forms"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
   x:Class="ToDo.CreateToDo">
   <ContentPage.Content>
     <StackLayout
       Padding="20">
       <Label
         Text="New Task"
         TextColor="Blue"
         FontSize="18" />
       <Entry
         x:Name="ToDo"
         Placeholder="New To Do Item"
         WidthRequest="150" />
       <Entry
         x:Name="Priority"
         Placeholder="Priority"
         WidthRequest="150" />
       <StackLayout
         Orientation="Horizontal">
         <Label
           Text="Due Date"
           VerticalOptions="End"
           TextColor="Green" />
         <DatePicker x:Name="Date"/>
       </StackLayout>
       <StackLayout
         Orientation="Horizontal">
         <Label
           Text="Due Time"
           VerticalOptions="End"
           TextColor="Green" />
         <TimePicker x:Name="Time" />
       </StackLayout>
       <StackLayout
         Orientation="Horizontal" HorizontalOptions="Center">
         <Button
           BackgroundColor="Green"
           TextColor="White"
           WidthRequest="75"
           Text="Save" 
           Clicked="OnSave"/>
         <Button
           BackgroundColor="Red"
           WidthRequest="75"
           TextColor="White"
           Text="Cancel" 
           Clicked="OnCancel"/>
         <Button
           BackgroundColor="Blue"
           WidthRequest="75"
           TextColor="White"
           Text="Review" 
           Clicked="OnReview"/>
       </StackLayout>
     </StackLayout>
   </ContentPage.Content>
 </ContentPage>

In the code behind we set up the ViewModel.  The constructor is overloaded, either to initialize the vm and the components, or to also retrieve the designated record from the database.

         public CreateToDo(int id) {
             vm = new CreateToDoViewModel();
             BindingContext = vm;
             InitializeComponent();
             ToDoItem toDoItem = App.Database.GetToDo(id);
             ToDo.Text = toDoItem.TaskName;
             Priority.Text = toDoItem.Priority;
             Date.Date = toDoItem.DueDate;
             Time.Time = toDoItem.DueDate.TimeOfDay;
             updateID = id;
         }
 
         public CreateToDo() {
             vm = new CreateToDoViewModel();
             BindingContext = vm;
             InitializeComponent();
         }
 

OnCancel calls clear which just resets the input.  OnReview will push to the review page (covered next week) and OnSave delegates to the ViewModel the job of saving the contents of the input fields,

 public void OnSave(object o, EventArgs e) {
     vm.AddTask(
         ToDo.Text, 
         Priority.Text, 
         Date.Date, 
         Time.Time.Hours,
         Time.Time.Minutes,
         Time.Time.Seconds,
         updateID,
         false); 
     Clear();
 
 }
 
 public void OnCancel(object o, EventArgs e) {
     Clear();
 }
 
 public void OnReview(object o, EventArgs e) {
     Clear();
     Navigation.PushAsync(new ListTasksPage());
 }
 
 private void Clear() {
     ToDo.Text = Priority.Text = String.Empty;
     Date.Date = DateTime.Now;
     Time.Time = new TimeSpan(
           DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
 }
 

The View Model

The work of saving a new task is as simple as taking in the input from the user and then assigning each value to its appropriate property in the model.  The only complexity is in transforming the due date, which is done with a helper method,

 public void AddTask(string todo,
                     string priority,
                     DateTime dueDate,
                     int hour,
                     int minute,
                     int second,
                     int updateID,
                     bool isDeleted) {
     var newToDo = new ToDoItem {
         TaskName = todo,
         Priority = priority,
         DueDate = SetDueDate(dueDate, hour, minute, second),
         IsDeleted = isDeleted,
         ID = updateID,
     };
     App.Database.SaveToDo(newToDo);
 }
 
 public DateTime SetDueDate(DateTime date, int hour, int minute, int second) {
     DateTime retVal = new DateTime(
                           date.Year,
                           date.Month,
                           date.Day,
                           hour,
                           minute,
                           second);
     
     return retVal;
 }

Database

As we’ve seen in previous entries in this series, you will need an interface for SQLite and a file, which I’ve called ToDoDatabase which will get the Connection through the DependencyService, create the table and do the CRUD operations.  I won’t reiterate all that code here as it is shown in earlier entries.

Next week: the review page, and then on to iOS and Android.  I’ll take the latter two much more slowly as we’ve not seen as much of native code in this series.

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in Essentials, Xamarin. Bookmark the permalink.

One Response to 52 Weeks of Xamarin: Week 13 – Writing It Thrice

Comments are closed.