在 Xamarin.Forms 專案,修正使用 Azure 行動應用的離線存取資料表功能
在這裡,我們將要把我們寫好的 Xamarin.Forms 專案,加入使用 Azure 行動應用服務功能,並且要能夠使用離線存取功能。
第一次準備工作
在您原先做好的 Xamarin.Forms 專案中,需要加入相關 NuGet 套件與建立一個
MobileServiceClient
物件加入 NuGet 套件
- 使用 Visual Studio 2015 打開
XFDoggy.sln
專案 - 滑鼠右擊
方案XFDoggy
,選擇管理方案的 NuGet套件
- 在
瀏覽
標籤頁次的搜尋文字輸入盒內,填入Microsoft.Azure.Mobile.Client.SQLiteStore
搜尋這個套件 - 點選核心PCL、Android、iOS 專案都要安裝這個套件,並點選
安裝
按鈕UWP 專案,請先不要安裝這個套件
加入 MobileServiceClient 離線初始化方法
- 在核心PCL專案的
Helpers
資料夾內,開啟MainHelper.cs
檔案 - 將 MainHelper 類別修改成底下的程式碼因為有些類別尚未新增進來,稍後再來修正相關命名空間錯誤這裡設定本地端的 SQLite 資料庫檔案名稱為 "localstore.db"要使用離線功能,需要在進行存取離線功能前,做些初始化動作,
AzureMobileOfflineInit()
將是要做這些事情。
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XFDoggy.Models;
using XFDoggy.Repositories;
namespace XFDoggy.Helpers
{
public static class MainHelper
{
/// <summary>
/// 指向 Azure Mobile App 服務的主要網址
/// </summary>
public static string MainURL = "https://xamarinazureday.azurewebsites.net";
/// <summary>
/// Azure Mobile App 線上版本的用戶端
/// </summary>
public static MobileServiceClient client = new MobileServiceClient(MainURL);
/// <summary>
/// 設定離線資料庫的檔案名稱
/// </summary>
public static string offlineDbPath = @"localstore.db";
/// <summary>
/// Azure Mobile App 離線版本的SQLite
/// </summary>
public static MobileServiceSQLiteStore store = new MobileServiceSQLiteStore(offlineDbPath);
public static 請假紀錄Manager 請假紀錄Manager = new 請假紀錄Manager();
/// <summary>
/// 進行 Azure Mobile App 的離線資料庫初始化動作
/// </summary>
public static void AzureMobileOfflineInit()
{
//取得Azure Mobile App 線上版本的用戶端
var store = MainHelper.store;
// 定義要用到的離線資料表
store.DefineTable<LeaveRecord>();
// 進行離線資料庫初始化
MainHelper.client.SyncContext.InitializeAsync(store);
}
}
}
關於建立 MobileServiceClient 物件的時候,需要傳遞的 URL 參數 ( 行動應用的主要 URL ),您可以從 Azure 儀表板中,找到XamarinAzureDay
行動應用程式,在這個XamarinAuzreDay App Service
刀鋒視窗中,預設會開啟概觀
標籤頁次,您可以從右方看到 URL 欄位,這裡就是這個行動應用的主要 URL。在這裡,請使用 Https 通訊協定
設定啟動應用程式的時候,要進行離線資料庫初始化
- 在核心 PCL 專案中,找到並打開 App.xaml.cs 檔案
- 將
OnInitialized
方法修改成為如下程式碼請修正相關命名空間錯誤
protected override void OnInitialized()
{
InitializeComponent();
//NavigationService.NavigateAsync($"xf:///MDPage?Menu={MenuItemEnum.關於.ToString()}/NaviPage/MainPage?title=多奇數位創意有限公司");
#region 進行離線資料庫初始化
MainHelper.AzureMobileOfflineInit();
#endregion
NavigationService.NavigateAsync($"LoginPage");
}
修改 Xamarin.Forms 專案
在這裡,我們將要修正 我要請假 申請作業的相關功能;在這裡,我們需要修正兩個頁面的 ViewModel,分別是,顯示清單與紀錄新增或修改頁面。原則上,我們在這裡並不會修正原有這個頁面中 Xamarin.Forms 的程式處理邏輯。
建立資料表會用到的資料模型
- 滑鼠右擊核心PCL專案的
Models
資料夾,點選加入
>類別
- 在對話窗中,點選
Visual C#
>類別
- 在名稱欄位輸入
LeaveRecord
,最後點選新增
按鈕 - 將 LeaveRecord 類別修改成底下的程式碼這裡我們需要加入
Version
欄位,這是要用於判斷本地端與伺服器端的紀錄版本是否一致。
public class LeaveRecord
{
public string Id { get; set; }
public string 申請人 { get; set; }
public DateTime 請假日期 { get; set; }
public TimeSpan 開始時間 { get; set; }
public int 請假時數 { get; set; }
public string 假別 { get; set; }
public string 請假理由 { get; set; }
public string 職務代理人 { get; set; }
[Version]
public string Version { get; set; }
}
建立 請假紀錄Manager
- 滑鼠右擊核心PCL專案的
Repositories
資料夾,點選加入
>類別
- 在對話窗中,點選
Visual C#
>類別
- 在名稱欄位輸入
請假紀錄Manager
,最後點選新增
按鈕 - 將 請假紀錄Manager 類別修改成底下的程式碼請修正相關命名空間錯誤
/// <summary>
/// 進行請假記錄的檔案存取功能
/// </summary>
public class 請假紀錄Manager
{
// 取得 Azure Mobile App 中的 請假紀錄 離線資料表物件
public IMobileServiceSyncTable<LeaveRecord> 請假紀錄Table;
// 進行同步工作的時候,產生的錯誤訊息
public string ErrorMessage = "";
public 請假紀錄Manager()
{
// 取得 請假記錄 離線資料表物件
請假紀錄Table = MainHelper.client.GetSyncTable<LeaveRecord>();
}
/// <summary>
/// 取得請假記錄清單
/// </summary>
/// <param name="是否要先進行同步工作"></param>
/// <returns></returns>
public async Task<ObservableCollection<LeaveRecord>> GetAsync(bool 是否要先進行同步工作 = false)
{
ErrorMessage = "";
try
{
if (是否要先進行同步工作)
{
// 將本地端的異動與伺服器端的紀錄進行同步處理
ErrorMessage = await SyncAsync();
}
// 取得所有的請假記錄集合
IEnumerable<LeaveRecord> items = await 請假紀錄Table
.OrderByDescending(x => x.請假日期)
.ToEnumerableAsync();
return new ObservableCollection<LeaveRecord>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
ErrorMessage = string.Format(@"Invalid sync operation: {0}", msioe.Message);
}
catch (Exception e)
{
ErrorMessage = string.Format(@"Sync error: {0}", e.Message);
}
return null;
}
/// <summary>
/// 使用 Id 鍵值進行查詢出這筆紀錄
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<LeaveRecord> LookupAsync(string id)
{
var fooObj = await 請假紀錄Table.LookupAsync(id);
return fooObj;
}
/// <summary>
/// 進行記錄更新
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public async Task UpdateAsync(LeaveRecord item)
{
await 請假紀錄Table.UpdateAsync(item);
}
/// <summary>
/// 新增一筆紀錄
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public async Task InsertAsync(LeaveRecord item)
{
await 請假紀錄Table.InsertAsync(item);
}
/// <summary>
/// 刪除這筆紀錄
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public async Task DeleteAsync(LeaveRecord item)
{
await 請假紀錄Table.DeleteAsync(item);
}
/// <summary>
/// 進行資料同步,並且取得最新線上的紀錄
/// </summary>
/// <returns></returns>
public async Task<string> SyncAsync()
{
var fooResult = "";
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
var fooClient = MainHelper.client;
await fooClient.SyncContext.PushAsync();
// 這裡可以設定要取得那些資料
var fooK = 請假紀錄Table.Where(x => x.請假日期 > DateTime.Now.AddMonths(-3));
await 請假紀錄Table.PullAsync(
//The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
//Use a different query name for each unique query in your program
"請假紀錄", fooK);
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling. A real application would handle the various errors like network conditions,
// server conflicts and others via the IMobileServiceSyncHandler.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//這裡要解決本地與伺服器端資料衝突的問題,底下是使用伺服器版本,蓋掉本機版本
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// 取消這筆本地端的資料異動,該異動紀錄將會從本地端移除
//await error.CancelAndDiscardItemAsync();
}
fooResult = @"Error executing sync operation. Item: {error.TableName} (" + error.Item["id"] + "). Operation discarded.";
}
}
return fooResult;
}
}
在 ViewMolde 加入這個資料表的 CRUD 行動應用服務功能
我要請假HomePage.xaml
- 在核心PCL專案內,找到資料夾
Views
內的我要請假HomePage.xaml
- 請使用底下 XAML 進行替換這個檔案內容
- 在這裡,我們需要在導航工具列中,加入一個
更新
按鈕,用來進行離線資料同步之用要這麼做的目的哪是,在這個頁面之中的所有紀錄異動,新增 修改 刪除 查詢,都將會使用離線資料庫來進行操作,當按下這個按鈕的時候,我們需要進行與遠端資料庫內的資料表進行同步更新動作。
<?xml version="1.0" encoding="utf-8" ?>
<!--NavigationPage.BackButtonTitle="上一頁" 這個設定,主要是針對 iOS 平台來使用到的-->
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
xmlns:localControls="clr-namespace:XFDoggy.CustomControls"
xmlns:behaviors="clr-namespace:XFDoggy.Behaviors"
xmlns:converters="clr-namespace:XFDoggy.Converters"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="XFDoggy.Views.我要請假HomePage"
Title="我要請假"
x:Name="ThisPage"
NavigationPage.BackButtonTitle="上一頁">
<ContentPage.Resources>
<!--ResourceDictionary 請參考:https://developer.xamarin.com/api/type/Xamarin.Forms.ResourceDictionary/-->
<ResourceDictionary>
<!--在這裡宣告一個數值轉換器 Converter,透過 x:Key 名字,可以在這個頁面中使用
若這個數值轉換器在很多頁面都會用到,可以在 App.xaml 中來宣告-->
<converters:假別Converter x:Key="假別Converter"/>
</ResourceDictionary>
</ContentPage.Resources>
<!--在導航工具列上,顯示一個可以新增紀錄的按鈕-->
<ContentPage.ToolbarItems>
<!--新增按鈕-->
<ToolbarItem Text="新增" Command="{Binding 點選新增請假紀錄項目Command}" />
<ToolbarItem Text="更新" Command="{Binding 點選更新請假紀錄項目Command}" />
</ContentPage.ToolbarItems>
<!--這個頁面的版面配置-->
<!--Data Binding 資料繫結請參考:https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/-->
<Grid
RowSpacing="0" ColumnSpacing="0"
BackgroundColor="{StaticResource 頁面背景Color}"
>
<!--該頁面的主要背景顏色設定-->
<Grid
RowSpacing="0" ColumnSpacing="0"
Margin="10"
BackgroundColor="{StaticResource 頁面內容本文背景Color}"
>
<Grid.RowDefinitions>
<!--這個部分為頁面標題與文字的空間規劃-->
<RowDefinition Height="40"/>
<!--這個部分是其他內容區域-->
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--頁面標題與文字-->
<Grid
RowSpacing="0" ColumnSpacing="0"
BackgroundColor="{StaticResource 頁面內容標題背景Color}"
>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label
Text="請假記錄清單"
Style="{StaticResource 頁面內文標題文字Style}"
/>
</Grid>
<!--清單資料-->
<!--ListView 請參考:https://developer.xamarin.com/api/type/Xamarin.Forms.ListView/-->
<ListView
HorizontalOptions="Fill" VerticalOptions="Fill"
Grid.Row="1"
ItemsSource="{Binding 請假紀錄項目清單}"
SelectedItem="{Binding 點選請假紀錄項目, Mode=TwoWay}"
SeparatorVisibility="None"
HasUnevenRows="True"
>
<!--這個部分為要使用 MVVM 綁定命令方式,將要透過 XAML Behavior來做到-->
<!--Xamarin.Forms Behavior 請參考:https://developer.xamarin.com/guides/xamarin-forms/behaviors/-->
<ListView.Behaviors>
<behaviors:EventHandlerBehavior EventName="ItemTapped">
<behaviors:InvokeCommandAction Command="{Binding 點選請假紀錄項目Command}" />
</behaviors:EventHandlerBehavior>
</ListView.Behaviors>
<ListView.ItemTemplate>
<!--定義每筆紀錄要出現的樣貌-->
<DataTemplate>
<!--ViewCell 請參考:https://developer.xamarin.com/api/type/Xamarin.Forms.ViewCell/-->
<ViewCell>
<Grid
RowSpacing="0" ColumnSpacing="0"
>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--最左方的假別-->
<Grid
RowSpacing="0" ColumnSpacing="0"
Grid.Row="0" Grid.Column="0"
Grid.RowSpan="2"
>
<BoxView
HorizontalOptions="Fill" VerticalOptions="Fill"
Color="Black"/>
<localControls:FontAwesomeLabel
Text="{Binding 假別, Converter={StaticResource 假別Converter}}"
Font="36"
TextColor="White"
HorizontalOptions="Center" VerticalOptions="Center"
/>
</Grid>
<!--請假日期-->
<Grid
RowSpacing="0" ColumnSpacing="0"
Grid.Row="0" Grid.Column="1"
>
<Label
Margin="10,0"
Text="{Binding 請假日期, StringFormat='{0:yyyy-MM-dd}'}"
TextColor="Black"
FontSize="24"
HorizontalOptions="Start" VerticalOptions="Start"
LineBreakMode="WordWrap">
</Label>
</Grid>
<!--開始時間-->
<Grid
RowSpacing="0" ColumnSpacing="0"
Grid.Row="1" Grid.Column="1"
>
<StackLayout
Orientation="Horizontal"
Spacing="0"
>
<Label
Margin="10,0"
Text="{Binding 開始時間, StringFormat='{0}'}"
TextColor="Black"
FontSize="24"
HorizontalOptions="Start" VerticalOptions="Start"
>
</Label>
<Label
Margin="10,0"
Text="{Binding 請假時數, StringFormat='{0}小時'}}"
TextColor="Black"
FontSize="24"
HorizontalOptions="Start" VerticalOptions="Start"
>
</Label>
</StackLayout>
</Grid>
<!--分隔線-->
<BoxView
Grid.Row="0" Grid.Column="0"
Grid.RowSpan="2" Grid.ColumnSpan="2"
HorizontalOptions="Fill" VerticalOptions="End"
HeightRequest="2"
Color="#8c8c8c" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</ContentPage>
差旅費用申請HomePageViewModel.cs
- 在核心PCL專案內,找到資料夾
ViewModels
內的我要請假HomePageViewModel.cs
- 請使用底下 C# 程式碼 進行替換這個檔案內容
- 由於這個頁面功能,當初是使用靜態資料,因此,我們要修改 ViewModel ,讓它可以使用 Azure 行動應用服務中的離線資料庫功能。
- 我們修正了
Init
方法,接收一個參數,用來判斷是否要執行同步更新 - 由於在進行同步更新動作的時候,會有很多突發異常,因此,我們需要將
MainHelper.請假紀錄Manager.GetAsync
呼叫,使用 try ... catch 捕捉起來 - 其他的修正則是要使用
MainHelper.請假紀錄Manager
這個物件,來進行資料存取動作
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using Prism.Navigation;
using Prism.Events;
using XFDoggy.Repositories;
using XFDoggy.Models;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using XFDoggy.Helpers;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using Prism.Services;
namespace XFDoggy.ViewModels
{
public class 我要請假HomePageViewModel : BindableBase, INavigationAware
{
#region Repositories (遠端或本地資料存取)
//請假紀錄Repository foo請假紀錄Repository = new 請假紀錄Repository();
#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>
/// 點選請假紀錄項目
/// </summary>
public 請假紀錄項目ViewModel 點選請假紀錄項目
{
get { return this._點選請假紀錄項目; }
set { this.SetProperty(ref this._點選請假紀錄項目, value); }
}
#endregion
#endregion
#region Field 欄位
public DelegateCommand 點選請假紀錄項目Command { get; set; }
public DelegateCommand 點選新增請假紀錄項目Command { get; set; }
public DelegateCommand 點選更新請假紀錄項目Command { get; set; }
public readonly IPageDialogService _dialogService;
private readonly INavigationService _navigationService;
private readonly IEventAggregator _eventAggregator;
#endregion
#region Constructor 建構式
public 我要請假HomePageViewModel(INavigationService navigationService, IEventAggregator eventAggregator,
IPageDialogService dialogService)
{
#region 相依性服務注入的物件
_dialogService = dialogService;
_eventAggregator = eventAggregator;
_navigationService = navigationService;
#endregion
#region 頁面中綁定的命令
點選請假紀錄項目Command = new DelegateCommand(async () =>
{
var fooID = 點選請假紀錄項目.ID;
點選請假紀錄項目 = null;
await _navigationService.NavigateAsync($"我要請假記錄修改Page?ID={fooID}");
});
點選新增請假紀錄項目Command = new DelegateCommand(async () =>
{
await _navigationService.NavigateAsync($"我要請假記錄修改Page");
});
點選更新請假紀錄項目Command = new DelegateCommand(async () =>
{
try
{
await Init(true);
}
catch (Exception ex)
{
await _dialogService.DisplayAlertAsync("錯誤", $"{ex.Message}", "確定");
}
});
#endregion
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public async void OnNavigatedTo(NavigationParameters parameters)
{
await Init();
}
#endregion
#region Navigation Events (頁面導航事件)
#endregion
#region 設計時期或者執行時期的ViewModel初始化
#endregion
#region 相關事件
#endregion
#region 相關的Command定義
#endregion
#region 其他方法
/// <summary>
/// 進行要顯示資料的初始化
/// </summary>
private async Task Init(bool 是否要先進行同步工作 = false)
{
var foo請假紀錄Collection = await MainHelper.請假紀錄Manager.GetAsync(是否要先進行同步工作);
#region 檢查進行同步更新的時候,是否有異常問題發生
if (foo請假紀錄Collection == null)
{
if (string.IsNullOrEmpty(MainHelper.請假紀錄Manager.ErrorMessage) == false)
{
await _dialogService.DisplayAlertAsync("錯誤", $"{MainHelper.請假紀錄Manager.ErrorMessage}", "確定");
return;
}
}
#endregion
請假紀錄項目清單.Clear();
foreach (var item in foo請假紀錄Collection)
{
請假紀錄項目清單.Add(new 請假紀錄項目ViewModel
{
ID = item.Id,
假別 = item.假別,
申請人 = item.申請人,
職務代理人 = item.職務代理人,
請假日期 = item.請假日期,
請假時數 = item.請假時數,
請假理由 = item.請假理由,
開始時間 = item.開始時間,
});
}
}
#endregion
}
}
我要請假記錄修改Page.xaml
在檔案
我要請假記錄修改Page.xaml
,並沒有需要做任何變動我要請假記錄修改PageViewModel.cs
- 在核心PCL專案內,找到資料夾
ViewModels
內的我要請假記錄修改PageViewModel.cs
- 請使用底下 C# 程式碼 進行替換這個檔案內容
- 由於這個頁面功能,當初是使用靜態資料,因此,我們要修改 ViewModel ,讓它可以使用 Azure 行動應用服務中的離線資料庫功能。
- 其他的修正則是要使用
MainHelper.請假紀錄Manager
這個物件,來進行資料存取動作
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using Prism.Navigation;
using Prism.Events;
using Prism.Services;
using XFDoggy.Models;
using XFDoggy.Repositories;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using XFDoggy.Helpers;
namespace XFDoggy.ViewModels
{
public class 我要請假記錄修改PageViewModel : BindableBase, INavigationAware
{
#region Repositories (遠端或本地資料存取)
請假紀錄Repository foo請假紀錄Repository = new 請假紀錄Repository();
#endregion
#region ViewModel Property (用於在 View 中作為綁定之用)
#region 請假紀錄項目
private 請假紀錄項目ViewModel _請假紀錄項目;
/// <summary>
/// 請假紀錄項目
/// </summary>
public 請假紀錄項目ViewModel 請假紀錄項目
{
get { return this._請假紀錄項目; }
set { this.SetProperty(ref this._請假紀錄項目, value); }
}
#endregion
#region 假別清單
private ObservableCollection<string> _假別清單 = new ObservableCollection<string>();
/// <summary>
/// 假別清單
/// </summary>
public ObservableCollection<string> 假別清單
{
get { return _假別清單; }
set { SetProperty(ref _假別清單, value); }
}
#endregion
#region 點選假別
private string _點選假別;
/// <summary>
/// 點選假別
/// </summary>
public string 點選假別
{
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 = "";
請假紀錄項目 foo請假紀錄項目;
LeaveRecord foo請假紀錄;
public DelegateCommand 刪除按鈕Command { get; set; }
public DelegateCommand 儲存按鈕Command { get; set; }
public DelegateCommand 取消按鈕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 頁面中綁定的命令
刪除按鈕Command = new DelegateCommand(async () =>
{
var fooAnswer = await _dialogService.DisplayAlertAsync("警告", "您確定刪除這筆請假記錄", "確定", "取消");
if (fooAnswer == true)
{
foo請假紀錄 = await MainHelper.請假紀錄Manager.LookupAsync(請假紀錄項目.ID);
if (foo請假紀錄 != null)
{
await MainHelper.請假紀錄Manager.DeleteAsync(foo請假紀錄);
}
await _navigationService.GoBackAsync();
}
});
儲存按鈕Command = new DelegateCommand(async () =>
{
var fooCheck = await Check資料完整性();
if (fooCheck == false)
{
return;
}
if (新增或修改 == 新增或修改Enum.新增)
{
foo請假紀錄 = new LeaveRecord
{
假別 = 點選假別,
申請人 = 請假紀錄項目.申請人,
職務代理人 = 請假紀錄項目.職務代理人,
請假日期 = 請假紀錄項目.請假日期,
請假時數 = 請假紀錄項目.請假時數,
請假理由 = 請假紀錄項目.請假理由,
開始時間 = 請假紀錄項目.開始時間,
};
await MainHelper.請假紀錄Manager.InsertAsync(foo請假紀錄);
await _navigationService.GoBackAsync();
}
else
{
foo請假紀錄 = await MainHelper.請假紀錄Manager.LookupAsync(請假紀錄項目.ID);
if (foo請假紀錄 != null)
{
foo請假紀錄.假別 = 點選假別;
foo請假紀錄.申請人 = 請假紀錄項目.申請人;
foo請假紀錄.職務代理人 = 請假紀錄項目.職務代理人;
foo請假紀錄.請假日期 = 請假紀錄項目.請假日期;
foo請假紀錄.請假時數 = 請假紀錄項目.請假時數;
foo請假紀錄.請假理由 = 請假紀錄項目.請假理由;
foo請假紀錄.開始時間 = 請假紀錄項目.開始時間;
await MainHelper.請假紀錄Manager.UpdateAsync(foo請假紀錄);
}
else
{
return;
}
await _navigationService.GoBackAsync();
}
await _navigationService.GoBackAsync();
});
取消按鈕Command = new DelegateCommand(async () =>
{
var fooAnswer = await _dialogService.DisplayAlertAsync("警告", "您確定取消這筆請假記錄", "確定", "取消");
if (fooAnswer == true)
{
await _navigationService.GoBackAsync();
}
});
#endregion
}
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;
}
await Init();
}
#endregion
#region Navigation Events (頁面導航事件)
#endregion
#region 設計時期或者執行時期的ViewModel初始化
#endregion
#region 相關事件
#endregion
#region 相關的Command定義
#endregion
#region 其他方法
/// <summary>
/// 進行要顯示資料的初始化
/// </summary>
private async Task Init()
{
#region 假別清單項目初始化
假別清單.Clear();
假別清單.Add("請選擇");
假別清單.Add("特休假");
假別清單.Add("事假");
假別清單.Add("病假");
#endregion
await foo請假紀錄Repository.Read();
if (string.IsNullOrEmpty(fooID) == true)
{
請假紀錄項目 = new 請假紀錄項目ViewModel();
點選假別 = 假別清單[0];
}
else
{
foo請假紀錄 = await MainHelper.請假紀錄Manager.LookupAsync(fooID);
//foo請假紀錄項目 = foo請假紀錄Repository.請假紀錄.FirstOrDefault(x => x.ID == fooID);
if (foo請假紀錄 == null)
{
請假紀錄項目 = new 請假紀錄項目ViewModel();
點選假別 = 假別清單[0];
}
else
{
請假紀錄項目 = new 請假紀錄項目ViewModel
{
ID = foo請假紀錄.Id,
假別 = foo請假紀錄.假別,
申請人 = foo請假紀錄.申請人,
職務代理人 = foo請假紀錄.職務代理人,
請假日期 = foo請假紀錄.請假日期,
請假時數 = foo請假紀錄.請假時數,
請假理由 = foo請假紀錄.請假理由,
開始時間 = foo請假紀錄.開始時間,
};
var fooObj = 假別清單.FirstOrDefault(x => x == 請假紀錄項目.假別);
if (fooObj != null)
{
點選假別 = fooObj;
}
else
{
點選假別 = 假別清單[0];
}
}
}
}
private async Task<bool> Check資料完整性()
{
if (點選假別 == 假別清單[0])
{
await _dialogService.DisplayAlertAsync("警告", "您尚未選擇請假類別", "確定");
return false;
}
return true;
}
#endregion
}
}
實際執行結果
在這裡,我們使用 Android 平台做為測試標的
我們在這裡可以新增任意數量紀錄,也可以隨意修改與刪除
檢測後端資料庫儲存結果
您可以使用 PostMan 來取得後端SQL資料庫內的 請假紀錄 資料表,實際儲存的紀錄內容。
在這裡,我們將會使用底下 URL 來查詢(記得要加入適當的 Header)