XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2017/04/17

Xamarin.Forms 與 Azure Mobile App Lab 11

在 Xamarin.Forms 專案,修正使用 Azure 行動應用的身分認證功能

在這裡,我們將要把我們寫好的 Xamarin.Forms 專案,加入使用 Azure 行動應用服務功能,並且要能夠進行身分驗證功能。
Mobile Apps 會使用 MobileServiceClient 的 LoginAsync 擴充方法,透過 App Service 驗證將使用者登入。

修改 Xamarin.Forms 專案

在這裡,我們將要修正 工作日報表 申請作業的相關功能。

建立資料表會用到的資料模型

  • 滑鼠右擊核心PCL專案的 Models 資料夾,點選 加入 > 類別
  • 在對話窗中,點選 Visual C# > 類別
  • 在名稱欄位輸入 WorkLog,最後點選 新增 按鈕
  • 將 WorkLog 類別修改成底下的程式碼
    public class WorkLog
    {
        public string Id { get; set; }
        public string 專案名稱 { get; set; }
        public DateTime 日期 { get; set; }
        public double 處理時間 { get; set; }
        public string 工作內容 { get; set; }
    }

在 ViewMolde 加入這個資料表的 CRUD 行動應用服務功能。

  • 在核心PCL專案內,找到資料夾 ViewModels 內的 填寫工作日報表HomePageViewModel.cs
  • 滑鼠雙擊這個檔案,打開它
  • 使用底下程式碼將其置換掉
    public class 差旅費用申請HomePageViewModel : BindableBase, INavigationAware
    {
        #region Repositories (遠端或本地資料存取)
        // 取得 Azure Mobile App 中的 差旅費用 資料表物件
        IMobileServiceTable<BusinessTripExpense> 差旅費用Table = MainHelper.client.GetTable<BusinessTripExpense>();
        #endregion

        #region ViewModel Property (用於在 View 中作為綁定之用)
        #region 差旅費用項目清單
        private ObservableCollection<差旅費用項目ViewModel> _差旅費用項目清單 = new ObservableCollection<差旅費用項目ViewModel>();
        /// <summary>
        /// 工作日報表項目清單
        /// </summary>
        public ObservableCollection<差旅費用項目ViewModel> 差旅費用項目清單
        {
            get { return _差旅費用項目清單; }
            set { SetProperty(ref _差旅費用項目清單, value); }
        }
        #endregion

        #region 點選差旅費用項目
        private 差旅費用項目ViewModel _點選差旅費用項目;
        /// <summary>
        /// PropertyDescription
        /// </summary>
        public 差旅費用項目ViewModel 點選差旅費用項目
        {
            get { return this._點選差旅費用項目; }
            set { this.SetProperty(ref this._點選差旅費用項目, value); }
        }
        #endregion

        #endregion

        #region Field 欄位
        BusinessTripExpense foo差旅費用;

        public DelegateCommand 點選差旅費用項目Command { get; set; }
        public DelegateCommand 新增按鈕Command { get; set; }

        private readonly INavigationService _navigationService;
        private readonly IEventAggregator _eventAggregator;
        #endregion

        #region Constructor 建構式
        public 差旅費用申請HomePageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
        {

            #region 相依性服務注入的物件

            _eventAggregator = eventAggregator;
            _navigationService = navigationService;
            #endregion

            #region 頁面中綁定的命令
            點選差旅費用項目Command = new DelegateCommand(async () =>
            {
                #region 建立要傳遞到下個頁面的參數
                var fooNavigationParameters = new NavigationParameters();
                fooNavigationParameters.Add("點選工作日報表項目", 點選差旅費用項目);
                fooNavigationParameters.Add("新增或修改", 新增或修改Enum.修改);
                #endregion

                //點選工作日報表項目 = null;

                await _navigationService.NavigateAsync("差旅費用申請紀錄修改Page", fooNavigationParameters);
            });

            新增按鈕Command = new DelegateCommand(async () =>
            {
                #region 建立要傳遞到下個頁面的參數
                var fooNavigationParameters = new NavigationParameters();
                fooNavigationParameters.Add("點選工作日報表項目", new 差旅費用項目ViewModel());
                fooNavigationParameters.Add("新增或修改", 新增或修改Enum.新增);
                #endregion

                await _navigationService.NavigateAsync("差旅費用申請紀錄修改Page", fooNavigationParameters);
            });
            #endregion

            #region 事件聚合器訂閱
            _eventAggregator.GetEvent<差旅費用紀錄維護動作Event>().Subscribe(async x =>
            {
                switch (x.新增或修改Enum)
                {
                    case 新增或修改Enum.新增:
                        #region Azure 行動應用服務的新增
                        foo差旅費用 = new BusinessTripExpense
                        {
                            備註 = x.差旅費用項目.備註,
                            出差日期 = x.差旅費用項目.出差日期,
                            國內外 = x.差旅費用項目.國內外,
                            地點 = x.差旅費用項目.地點,
                            是否有單據 = x.差旅費用項目.是否有單據,
                            費用 = x.差旅費用項目.費用,
                            項目名稱 = x.差旅費用項目.項目名稱,
                            類型 = x.差旅費用項目.類型,
                        };
                        await 差旅費用Table.InsertAsync(foo差旅費用);
                        await Init();
                        #endregion
                        break;
                    case 新增或修改Enum.修改:
                        #region 更新欄位資料
                        var fooObj = 差旅費用項目清單.FirstOrDefault(z => z.ID == x.差旅費用項目.ID);
                        if (fooObj != null)
                        {
                            var fooIdx = 差旅費用項目清單.IndexOf(fooObj);
                            差旅費用項目清單[fooIdx] = x.差旅費用項目;
                        }

                        #region Azure 行動應用服務的新增
                        foo差旅費用 = await 差旅費用Table.LookupAsync(x.差旅費用項目.ID);
                        foo差旅費用.備註 = x.差旅費用項目.備註;
                        foo差旅費用.出差日期 = x.差旅費用項目.出差日期;
                        foo差旅費用.國內外 = x.差旅費用項目.國內外;
                        foo差旅費用.地點 = x.差旅費用項目.地點;
                        foo差旅費用.是否有單據 = x.差旅費用項目.是否有單據;
                        foo差旅費用.費用 = x.差旅費用項目.費用;
                        foo差旅費用.項目名稱 = x.差旅費用項目.項目名稱;
                        foo差旅費用.類型 = x.差旅費用項目.類型;

                        await 差旅費用Table.UpdateAsync(foo差旅費用);
                        #endregion
                        #endregion
                        break;
                    case 新增或修改Enum.刪除:
                        var fooObjDel = 差旅費用項目清單.FirstOrDefault(z => z.ID == x.差旅費用項目.ID);
                        if (fooObjDel != null)
                        {
                            差旅費用項目清單.Remove(fooObjDel);
                        }

                        #region Azure 行動應用服務的新增
                        foo差旅費用 = await 差旅費用Table.LookupAsync(x.差旅費用項目.ID);
                        await 差旅費用Table.DeleteAsync(foo差旅費用);
                        #endregion
                        break;
                    default:
                        break;
                }
            });
            #endregion
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public async void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("差旅費用紀錄維護動作內容") == false)
            {
                await Init();
            }
        }
        #endregion

        #region Navigation Events (頁面導航事件)
        #endregion

        #region 設計時期或者執行時期的ViewModel初始化
        #endregion

        #region 相關事件
        #endregion

        #region 相關的Command定義
        #endregion

        #region 其他方法
        /// <summary>
        /// 進行要顯示資料的初始化
        /// </summary>
        private async Task Init()
        {
            差旅費用項目ViewModel foo差旅費用項目;

            差旅費用項目清單.Clear();

            #region 呼叫 Azure 行動應用後台,取得最新後台資料表的清單
            var fooList = await 差旅費用Table.OrderByDescending(x => x.出差日期).ToListAsync();
            foreach (var item in fooList)
            {
                foo差旅費用項目 = new 差旅費用項目ViewModel
                {
                    ID = item.Id,
                    出差日期 = item.出差日期,
                    項目名稱 = item.項目名稱,
                    地點 = item.地點,
                    類型 = item.類型,
                    是否有單據 = item.是否有單據,
                    國內外 = item.國內外,
                    費用 = item.費用,
                    備註 = item.備註,
                };
                差旅費用項目清單.Add(foo差旅費用項目);
            }
            #endregion
        }
        #endregion

    }
  • 在核心PCL專案內,找到資料夾 ViewModels 內的 填寫工作日報表記錄修改PageViewModel.cs
  • 滑鼠雙擊這個檔案,打開它
  • 使用底下程式碼將其置換掉
    public class 填寫工作日報表記錄修改PageViewModel : BindableBase, INavigationAware
    {
        #region Repositories (遠端或本地資料存取)
        //工作日報表Repository foo工作日報表Repository = new 工作日報表Repository();
        IMobileServiceTable<WorkLog> WorkLogTable = MainHelper.client.GetTable<WorkLog>();
        #endregion

        #region ViewModel Property (用於在 View 中作為綁定之用)

        #region 工作日報表項目
        private 工作日報表項目ViewModel _工作日報表項目;
        /// <summary>
        /// 工作日報表項目
        /// </summary>
        public 工作日報表項目ViewModel 工作日報表項目
        {
            get { return this._工作日報表項目; }
            set { this.SetProperty(ref this._工作日報表項目, value); }
        }
        #endregion

        #region Title
        private string _Title;
        /// <summary>
        /// Title
        /// </summary>
        public string Title
        {
            get { return this._Title; }
            set { this.SetProperty(ref this._Title, value); }
        }
        #endregion

        #region 顯示刪除按鈕
        private bool _顯示刪除按鈕;
        /// <summary>
        /// 顯示刪除按鈕
        /// </summary>
        public bool 顯示刪除按鈕
        {
            get { return this._顯示刪除按鈕; }
            set { this.SetProperty(ref this._顯示刪除按鈕, value); }
        }
        #endregion

        #endregion

        #region Field 欄位
        新增或修改Enum 新增或修改 = 新增或修改Enum.修改;
        string fooID = "";
        WorkLog 工作日報表Model;

        public DelegateCommand 儲存按鈕Command { get; set; }
        public DelegateCommand 取消按鈕Command { get; set; }
        public DelegateCommand Can刪除按鈕Command { get; set; }

        private readonly INavigationService _navigationService;
        private readonly IEventAggregator _eventAggregator;
        public readonly IPageDialogService _dialogService;
        #endregion

        #region Constructor 建構式
        public 填寫工作日報表記錄修改PageViewModel(INavigationService navigationService, IEventAggregator eventAggregator,
            IPageDialogService dialogService)
        {
            #region 相依性服務注入的物件

            _dialogService = dialogService;
            _eventAggregator = eventAggregator;
            _navigationService = navigationService;
            #endregion

            #region 頁面中綁定的命令 
            Can刪除按鈕Command = new DelegateCommand(async () =>
            {
                var fooAnswer = await _dialogService.DisplayAlertAsync("警告", "您確定刪除這筆請假記錄", "確定", "取消");
                if (fooAnswer == true)
                {
                    工作日報表Model = await WorkLogTable.LookupAsync(fooID);
                    if (工作日報表Model != null)
                    {
                        await WorkLogTable.DeleteAsync(工作日報表Model);

                        _eventAggregator.GetEvent<漢堡按鈕啟動或隱藏Event>().Publish(true);
                        await _navigationService.GoBackAsync();
                    }
                    else
                    {
                        return;
                    }
                }
            },
            () =>
            {
                //設定這個命令在何種狀態下可以被執行
                return 新增或修改 == 新增或修改Enum.新增 ? false : true;
            }
            );

            儲存按鈕Command = new DelegateCommand(async () =>
            {
                var fooCheck = await Check資料完整性();
                if (fooCheck == false)
                {
                    return;
                }

                if (新增或修改 == 新增或修改Enum.新增)
                {
                    工作日報表Model = new WorkLog();
                    工作日報表Model.專案名稱 = 工作日報表項目.專案名稱;
                    工作日報表Model.工作內容 = 工作日報表項目.工作內容;
                    工作日報表Model.日期 = 工作日報表項目.日期;
                    工作日報表Model.處理時間 = 工作日報表項目.處理時間;

                    await WorkLogTable.InsertAsync(工作日報表Model);

                    _eventAggregator.GetEvent<漢堡按鈕啟動或隱藏Event>().Publish(true);
                    await _navigationService.GoBackAsync();
                    return;
                }
                else
                {
                    工作日報表Model = await WorkLogTable.LookupAsync(fooID);
                    if (工作日報表Model != null)
                    {
                        工作日報表Model.Id = 工作日報表項目.ID;
                        工作日報表Model.專案名稱 = 工作日報表項目.專案名稱;
                        工作日報表Model.工作內容 = 工作日報表項目.工作內容;
                        工作日報表Model.日期 = 工作日報表項目.日期;
                        工作日報表Model.處理時間 = 工作日報表項目.處理時間;

                        await WorkLogTable.UpdateAsync(工作日報表Model);

                        _eventAggregator.GetEvent<漢堡按鈕啟動或隱藏Event>().Publish(true);
                        await _navigationService.GoBackAsync();
                        return;
                    }
                    else
                    {
                        return;
                    }
                }
            });

            取消按鈕Command = new DelegateCommand(async () =>
            {
                var fooAnswer = await _dialogService.DisplayAlertAsync("警告", "您確定取消這筆請假記錄", "確定", "取消");
                if (fooAnswer == true)
                {
                    _eventAggregator.GetEvent<漢堡按鈕啟動或隱藏Event>().Publish(true);
                    await _navigationService.GoBackAsync();
                }
            });
            #endregion

            _eventAggregator.GetEvent<漢堡按鈕啟動或隱藏Event>().Publish(false);
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public async void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("ID") == true)
            {
                fooID = parameters["ID"] as string;
                新增或修改 = 新增或修改Enum.修改;
                Title = "工作日報記錄修改";
                顯示刪除按鈕 = true;
            }
            else
            {
                fooID = "";
                新增或修改 = 新增或修改Enum.新增;
                Title = "工作日報記錄新增";
                顯示刪除按鈕 = false;
            }

            // 要求檢查這個命令是否可以被使用
            Can刪除按鈕Command.RaiseCanExecuteChanged();

            await Init();
        }
        #endregion

        #region Navigation Events (頁面導航事件)
        #endregion

        #region 設計時期或者執行時期的ViewModel初始化
        #endregion

        #region 相關事件
        #endregion

        #region 相關的Command定義
        #endregion

        #region 其他方法
        private async Task Init()
        {
            if (string.IsNullOrEmpty(fooID) == true)
            {
                工作日報表項目 = new 工作日報表項目ViewModel();
            }
            else
            {
                工作日報表Model = await WorkLogTable.LookupAsync(fooID);
                if (工作日報表Model == null)
                {
                    工作日報表項目 = new 工作日報表項目ViewModel();
                }
                else
                {
                    工作日報表項目 = new 工作日報表項目ViewModel
                    {
                        ID = 工作日報表Model.Id,
                        專案名稱 = 工作日報表Model.專案名稱,
                        工作內容 = 工作日報表Model.工作內容,
                        日期 = 工作日報表Model.日期,
                        是否顯示日期區塊 = true,
                        當日累計工時 = 0,
                        處理時間 = 工作日報表Model.處理時間,
                    };
                }
            }
        }

        private async Task<bool> Check資料完整性()
        {
            if (string.IsNullOrEmpty(工作日報表項目.專案名稱) == true)
            {
                await _dialogService.DisplayAlertAsync("警告", "專案名稱 必須要輸入", "確定");
                return false;
            }

            return true;
        }
        #endregion

    }

設計身分驗證機制

定義與實作 IAuthenticate

為了驗證 Xamarin Forms 專案,請在應用程式的可攜式類別庫中定義 IAuthenticate 介面。 然後,將 [登入] 按鈕新增至可攜式類別庫中定義的使用者介面,讓您按一下來開始驗證。 驗證成功後,將會從行動應用程式後端載入資料。

定義 IAuthenticate

  • 打開核心PCL專案的 App.xaml.cs 檔案
  • 在 App 類別定義之前緊接著加入下列 IAuthenticate 介面定義
    /// <summary>
    /// 要透過 Azure 行動應用服務進行身分驗證的介面
    /// 實際實作的部分,會在每個原生專案中實作與
    /// </summary>
    public interface IAuthenticate
    {
        Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式);
    }
請修正相關命名空間錯誤
  • 將下列靜態成員新增至 App 類別,以使用平台特定實作來初始化介面。
        /// <summary>
        /// 該介面所實際物件,會在原生專案中,指定實際實作物件
        /// </summary>
        public static IAuthenticate Authenticator { get; private set; }

        /// <summary>
        /// Azure 行動應用服務進行身分驗證的介面初始化方法
        /// </summary>
        /// <param name="authenticator"></param>
        public static void Init(IAuthenticate authenticator)
        {
            Authenticator = authenticator;
        }
  • 底下為 App.xaml.cs 的完整程式碼
using Microsoft.WindowsAzure.MobileServices;
using Prism.Unity;
using System.Threading.Tasks;
using XFDoggy.Helpers;
using XFDoggy.Models;
using XFDoggy.Views;

namespace XFDoggy
{
using Microsoft.WindowsAzure.MobileServices;
using Prism.Unity;
using System.Threading.Tasks;
using XFDoggy.Helpers;
using XFDoggy.Models;
using XFDoggy.Views;

namespace XFDoggy
{
    #region Azure Mobile 身分驗證介面
    /// <summary>
    /// 要透過 Azure 行動應用服務進行身分驗證的介面
    /// 實際實作的部分,會在每個原生專案中實作與
    /// </summary>
    public interface IAuthenticate
    {
        Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式);
    }
    #endregion

    public partial class App : PrismApplication
    {
        #region Azure Mobile 身分驗證介面初始化
        /// <summary>
        /// 該介面所實際物件,會在原生專案中,指定實際實作物件
        /// </summary>
        public static IAuthenticate Authenticator { get; private set; }

        /// <summary>
        /// Azure 行動應用服務進行身分驗證的介面初始化方法
        /// </summary>
        /// <param name="authenticator"></param>
        public static void Init(IAuthenticate authenticator)
        {
            Authenticator = authenticator;
        }
        #endregion

        public App(IPlatformInitializer initializer = null) : base(initializer) { }

        protected override void OnInitialized()
        {
            InitializeComponent();

            //NavigationService.NavigateAsync($"xf:///MDPage?Menu={MenuItemEnum.關於.ToString()}/NaviPage/MainPage?title=多奇數位創意有限公司");

            #region 進行離線資料庫初始化
            MainHelper.AzureMobileOfflineInit();
            #endregion

            NavigationService.NavigateAsync($"LoginPage");
        }

        protected override void RegisterTypes()
        {
            Container.RegisterTypeForNavigation<MainPage>();
            Container.RegisterTypeForNavigation<MDPage>();
            Container.RegisterTypeForNavigation<NaviPage>();
            Container.RegisterTypeForNavigation<OnCall電話Page>();
            Container.RegisterTypeForNavigation<我要請假HomePage>();
            Container.RegisterTypeForNavigation<我要請假記錄修改Page>();
            Container.RegisterTypeForNavigation<差旅費用申請HomePage>();
            Container.RegisterTypeForNavigation<差旅費用申請紀錄修改Page>();
            Container.RegisterTypeForNavigation<最新消息HomePage>();
            Container.RegisterTypeForNavigation<填寫工作日報表HomePage>();
            Container.RegisterTypeForNavigation<填寫工作日報表記錄修改Page>();
            Container.RegisterTypeForNavigation<LoginPage>();
            Container.RegisterTypeForNavigation<LoginPage>();
        }
    }
}

在 Android 中,實作 IAuthenticate

  • 在原生 Android 專案的 開啟 MainActivity.cs 檔案
  • 更新 MainActivity 類別來實作 IAuthenticate 介面
    更新 MainActivity 類別,新增 IAuthenticate 介面所需的 MobileServiceUser 欄位和 Authenticate 方法
  • 在 MainActivity 類別的 OnCreate 方法中,在呼叫 LoadApplication() 之前,需要將核心PCL內的 Authenticator 介面,指定這裡的實作物件
  • 底下為修正後的 MainActivity 類別定義
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IAuthenticate
    {
        #region Azure 行動應用之身分驗證用到程式碼

        // Define a authenticated user.
        private MobileServiceUser user;


        public async Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式)
        {
            // 驗證結果
            var success = false;
            // 要顯示的訊息
            var message = string.Empty;
            try
            {
                // 每次登入的時候,都要強制重新登入,不使用上次登入的資訊
                CookieManager.Instance.RemoveAllCookie();
                await MainHelper.client.LogoutAsync();
                // 呼叫 Azure Mobile 用戶端的 LoginAsync 方法,依據指定的登入類型,進行身分驗證登入
                user = await MainHelper.client.LoginAsync(this, p登入方式);
                if (user != null)
                {
                    message = string.Format("you are now signed-in as {0}.", user.UserId);
                    success = true;
                }
            }
            catch (Exception ex)
            {
                message = ex.Message;
            }

            // 顯示登入成功或者失敗.
            //AlertDialog.Builder builder = new AlertDialog.Builder(this);
            //builder.SetMessage(message);
            //builder.SetTitle("Sign-in result");
            //builder.Create().Show();

            return success;
        }
        #endregion

        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.tabs;
            ToolbarResource = Resource.Layout.toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);

            #region Azure 行動應用之身分驗證用到程式碼
            // 將在 Android 原生平台實作的 IAuthenticate 物件,指定到 核心PCL 專案內
            App.Init((IAuthenticate)this);
            #endregion

            LoadApplication(new App(new AndroidInitializer()));
        }
    }

在 iOS 中,實作 IAuthenticate

更新 AppDelegate 類別來實作 IAuthenticate 介面
  • 打開原生 iOS 專案的 AppDelegate.cs 檔案
  • 將底下程式碼替換掉 AppDelegate 類別定義
  • 在這裡,我們新增了一個類別欄位 private MobileServiceUser user 用來儲存認證通過的使用者資訊
  • 實作出 IAuthenticate 介面中的 Authenticate 方法,我們依據傳入要認證的類型,呼叫 LoginAsync 方法,顯示出登入頁面。
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IAuthenticate
    {
        #region Azure Mobile 身分驗證
        // Define a authenticated user.
        private MobileServiceUser user;
        public async Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式)
        {
            var success = false;
            var message = string.Empty;
            try
            {
                // Sign in with Facebook login using a server-managed flow.
                if (user == null)
                {
                    // 每次登入的時候,都要強制重新登入,不使用上次登入的資訊
                    foreach (var cookie in NSHttpCookieStorage.SharedStorage.Cookies)
                    {
                        NSHttpCookieStorage.SharedStorage.DeleteCookie(cookie);
                    }
                    await MainHelper.client.LogoutAsync();
                    // 呼叫 Azure Mobile 用戶端的 LoginAsync 方法,依據指定的登入類型,進行身分驗證登入
                    user = await MainHelper.client.LoginAsync(UIApplication.SharedApplication.KeyWindow.RootViewController, p登入方式);
                    if (user != null)
                    {
                        message = string.Format("You are now signed-in as {0}.", user.UserId);
                        success = true;
                    }
                }
            }
            catch (Exception ex)
            {
                message = ex.Message;
            }

            // Display the success or failure message.
            UIAlertView avAlert = new UIAlertView("Sign-in result", message, null, "OK", null);
            avAlert.Show();

            return success;
        }

        #endregion

        //
        // This method is invoked when the application has loaded and is ready to run. In this 
        // method you should instantiate the window, load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method, or iOS will terminate your application.
        //
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App(new iOSInitializer()));

            // http://stackoverflow.com/questions/24521355/azure-mobile-services-invalid-operation-exception-platform-specific-assembly-n
            Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();

            return base.FinishedLaunching(app, options);
        }
    }

將驗證加入登入頁面中

  • 打開核心PCL專案的 ViewModels 資料夾內的 LoginPageViewModel.cs
  • 在這裡,我們修正了這兩個命令 Facebook登入Command / Google登入Command
    只有當身分認證成功之後,才會進入到這個應用程式的首頁
  • 修正建構式如同底下程式碼
        public LoginPageViewModel(INavigationService navigationService, IPageDialogService dialogService)
        {

            _dialogService = dialogService;
            _navigationService = navigationService;

            登入Command = new DelegateCommand(async () =>
            {
                await _navigationService.NavigateAsync($"xf:///MDPage?Menu={MenuItemEnum.關於.ToString()}/NaviPage/MainPage?title=多奇數位創意有限公司");
            });
            Facebook登入Command = new DelegateCommand(async () =>
            {
                var fooResult  = await App.Authenticator.Authenticate(Microsoft.WindowsAzure.MobileServices.MobileServiceAuthenticationProvider.Facebook);
                if(fooResult == true)
                {
                    await _navigationService.NavigateAsync($"xf:///MDPage?Menu={MenuItemEnum.關於.ToString()}/NaviPage/MainPage?title=多奇數位創意有限公司");
                }
            });
            Google登入Command = new DelegateCommand(async () =>
            {
                var fooResult = await App.Authenticator.Authenticate(Microsoft.WindowsAzure.MobileServices.MobileServiceAuthenticationProvider.Google);
                if (fooResult == true)
                {
                    await _navigationService.NavigateAsync($"xf:///MDPage?Menu={MenuItemEnum.關於.ToString()}/NaviPage/MainPage?title=多奇數位創意有限公司");
                }
            });
        }

實際執行結果