-
Notifications
You must be signed in to change notification settings - Fork 24
Creating a Xamarin Forms client app
stefffdev edited this page Jul 21, 2020
·
10 revisions
This documentation assumes that you have a working Xamarin Forms app. We will add the NubeSync client framework and a SQLite storage for the offline cache.
You can download the complete source code for this sample here: https://github.com/stefffdev/NubeSync.Samples/tree/master/Clients/Xamarin.Forms/NubeSync.Mobile
Add the NubeSync.Client.SQLiteStore nuget package to all projects, including the client projects.
Similar to the server project the DTO (Data Transfer Object) contains the structure of the records to be synced with the server.
- Add a file TodoItem.cs to the project
- Add the following using:
using Nube.Client.Data;- Add the following content to the class:
public class TodoItem : NubeTable
{
public string Name { get; set; }
public bool IsChecked { get; set; }
}Change your MainPage.xaml to look like this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="NubeSync.Mobile.MainPage"
Appearing="ContentPage_Appearing">
<StackLayout>
<Button Text="Add Item" Clicked="Add_Button_Clicked" />
<Button Text="Sync" Clicked="Sync_Button_Clicked" />
<CollectionView x:Name="collectionView">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Entry Text="{Binding Name}" Unfocused="Entry_Unfocused" />
<CheckBox Grid.Column="1" IsChecked="{Binding IsChecked}" CheckedChanged="CheckBox_CheckedChanged" />
<Button Grid.Column="2" Text="Delete" Clicked="Delete_Button_Clicked" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>Make your MainPage.xaml.cs look like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using NubeSync.Client;
using NubeSync.Client.SQLiteStore;
using SQLite;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace NubeSync.Mobile
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
private NubeSQLiteDataStore _dataStore;
private NubeClient _nubeClient;
public MainPage()
{
InitializeComponent();
var databasePath = Path.Combine(FileSystem.AppDataDirectory, "offline.db");
_dataStore = new NubeSQLiteDataStore(databasePath);
// this is needed for local debugging
var clientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
};
var httpClient = new HttpClient(clientHandler);
NubeClientConfiguration configuration = new NubeClientConfiguration()
{
Server = "https://localhost:5001/"
};
if (DeviceInfo.Platform == DevicePlatform.Android)
{
configuration = new NubeClientConfiguration() { Server = "https://10.0.2.2:5001/" };
}
_nubeClient = new NubeClient(_dataStore, configuration, httpClient);
}
private async void ContentPage_Appearing(object sender, EventArgs e)
{
await _dataStore.InitializeAsync();
await _nubeClient.AddTableAsync<TodoItem>("todoitems");
await RefreshItemsAsync();
}
private async Task RefreshItemsAsync()
{
var list = (await _nubeClient.GetAllAsync<TodoItem>()).ToList().OrderBy(i => i.CreatedAt);
collectionView.ItemsSource = list;
}
private async Task SyncAsync()
{
await _nubeClient.PushChangesAsync();
await _nubeClient.PullTableAsync<TodoItem>();
await RefreshItemsAsync();
}
private async void Add_Button_Clicked(object sender, EventArgs e)
{
var item = new TodoItem() { Name = "New Item" };
await _nubeClient.SaveAsync(item);
await SyncAsync();
}
private async void Delete_Button_Clicked(object sender, EventArgs e)
{
if (sender is Button button && button.BindingContext is TodoItem item)
{
await _nubeClient.DeleteAsync(item);
await _nubeClient.PushChangesAsync();
await RefreshItemsAsync();
}
}
private async void Sync_Button_Clicked(object sender, EventArgs e)
{
await SyncAsync();
}
private async void Entry_Unfocused(object sender, FocusEventArgs e)
{
if (sender is Entry entry && entry.BindingContext is TodoItem item)
{
item.Name = entry.Text;
await _nubeClient.SaveAsync(item);
await _nubeClient.PushChangesAsync();
}
}
private async void CheckBox_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
if (sender is CheckBox checkBox && checkBox.BindingContext is TodoItem item)
{
item.IsChecked = checkBox.IsChecked;
await _nubeClient.SaveAsync(item);
await _nubeClient.PushChangesAsync();
}
}
}
}