I'm working through a Xamarin Forms PCL Sqlite / Azure Mobile Services sync example, named TodoAzureSync.iOS. The Azure Mobile sync part is working fine. The problem is - when I pull my network connection, add a new TodoItem, navigate back to the List View - it will not show in the List View. Still in offline mode, I stop and restart the app - my List View has no items in it. However, when I put the network back on, and restart the app - all my Todo items will show up INCLUDING the one I have entered in the offline mode! This tells me that, even though my offline item did not show up in the List View during offline period, it was actually recorded into the local Sqlite instance, and, when the network was re-establshied, it synced up with Azure back-end, and showed up in the List View.
My question is: how can I make my offline items actually show up in the List View EVEN during the offline mode?
Here is the TodoItemManager (PCL) code, which is responsible for all CRUD operations:
using System;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.WindowsAzure.MobileServices.Sync;
namespace TodoXaml
{
///
/// Manager classes are an abstraction on the data access layers
///
public class TodoItemManager {
IMobileServiceSyncTable<TodoItem> todoTable;
IMobileServiceClient client;
public TodoItemManager (IMobileServiceClient client, IMobileServiceSyncTable<TodoItem> todoTable)
{
this.client = client;
this.todoTable = todoTable;
}
public async Task<TodoItem> GetTaskAsync(string id)
{
try
{
await SyncAsync();
return await todoTable.LookupAsync(id);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"INVALID {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(@"ERROR {0}", e.Message);
}
return null;
}
public async Task<List<TodoItem>> GetTasksAsync ()
{
try
{
await SyncAsync();
return new List<TodoItem> (await todoTable.ReadAsync());
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"INVALID {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(@"ERROR {0}", e.Message);
}
return null;
}
public async Task SaveTaskAsync (TodoItem item)
{
if (item.ID == null)
await todoTable.InsertAsync(item);
else
await todoTable.UpdateAsync(item);
//await SyncAsync ();
}
public async Task DeleteTaskAsync (TodoItem item)
{
try
{
await todoTable.DeleteAsync(item);
//await SyncAsync ();
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"INVALID {0}", msioe.Message);
}
catch (Exception e)
{
Debug.WriteLine(@"ERROR {0}", e.Message);
}
}
public async Task SyncAsync()
{
try
{
await this.client.SyncContext.PushAsync();
await this.todoTable.PullAsync();
}
catch (MobileServiceInvalidOperationException e)
{
Debug.WriteLine(@"Sync Failed: {0}", e.Message);
}
}
}
}
And here is the iOS AppDelegate:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using TodoXaml;
using Xamarin.Forms;
using System.IO;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using System.Threading.Tasks;
namespace TodoXaml
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
UIWindow window;
MobileServiceClient Client;
IMobileServiceSyncTable<TodoItem> todoTable;
TodoItemManager todoItemManager;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
Forms.Init ();
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
#region Azure stuff
CurrentPlatform.Init ();
SQLitePCL.CurrentPlatform.Init();
Client = new MobileServiceClient (
Constants.Url,
Constants.Key);
#region Azure Sync stuff
// http://azure.microsoft.com/en-us/documentation/articles/mobile-services-xamarin-android-get-started-offline-data/
// new code to initialize the SQLite store
InitializeStoreAsync().Wait();
#endregion
todoTable = Client.GetSyncTable<TodoItem>();
todoItemManager = new TodoItemManager(Client, todoTable);
App.SetTodoItemManager (todoItemManager);
#endregion region
#region Text to Speech stuff
App.SetTextToSpeech (new Speech ());
#endregion region
// If you have defined a view, add it here:
// window.RootViewController = navigationController;
window.RootViewController = App.GetMainPage ().CreateViewController ();
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
public async Task InitializeStoreAsync()
{
string path = "syncstore.db";
var store = new MobileServiceSQLiteStore (path);
store.DefineTable<TodoItem> ();
//await Client.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());
await Client.SyncContext.InitializeAsync (store);
}
}
}
-Eugene