XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2016/10/06

企業之差旅費用 跨平台應用程式開發 (3) 建立CRUD等相關服務

當您已經建立起 Xamarin.Forms 開發專案與加入了相關套件與插件,並且也在不同的專案內加入了分類用的資料夾,接下來,您將會需要將基礎服務開發出來。
在這個階段的練習,您將會需要完成學會底下需求:
  1. 建立資料模型 (Model)
  2. 建立全域靜態變數
  3. 建立呼叫後端 Web API 的服務類別
  4. 建立判斷現在是否在Debug模式或者Release模式的介面與其實作
  5. 建立全域XAML樣式
這篇章節的練習專案的原始程式碼將會存放在 GitHubhttps://github.com/vulcanlee/XFAppSample/tree/master/XFDoggy/2.InfraService 內

建立資料模型 (Model)

使用者類別

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Models 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 User,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

User.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Models
{
    public class User
    {
        public int ID { get; set; }
        public string Account { get; set; }
        public string Password { get; set; }
    }
}

使用者認證與認證結果類別

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Models 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 AuthUser,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

AuthUser.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Models
{
    public class AuthUser
    {
        public string Account { get; set; }
        public string Password { get; set; }
    }
    public class AuthUserResult
    {
        public bool Status { get; set; }
    }
}

差旅費用類別項目定義類別

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Models 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 TravelExpensesCategory,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

TravelExpensesCategory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Models
{
    public class TravelExpensesCategory
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}

差旅費用項目紀錄類別

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Models 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 TravelExpense,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

TravelExpense.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Models
{
    public class TravelExpense
    {
        public int ID { get; set; }
        public string Account { get; set; }
        public DateTime TravelDate { get; set; }
        public string Category { get; set; }
        public string Title { get; set; }
        public string Location { get; set; }
        public double Expense { get; set; }
        public string Memo { get; set; }
        public bool Domestic { get; set; }
        public bool HasDocument { get; set; }
        public DateTime Updatetime { get; set; }
    }
}

建立輔助支援類別

系統使用的資料

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Helps 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 AppData,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

AppData.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using XFDoggy.Models;
using XFDoggy.Services;

namespace XFDoggy.Helps
{
    public class AppData
    {
        public static string UserUrl { get; set; } = "http://xamarindoggy.azurewebsites.net/api/user";
        public static string TravelExpensesCategoryUrl { get; set; } = "http://xamarindoggy.azurewebsites.net/api/TravelExpensesCategory";
        public static string UserAuthUrl { get; set; } = "http://xamarindoggy.azurewebsites.net/api/User/Auth";
        //public static string TravelExpenseGetUrl { get; set; } = "http://xamarindoggy.azurewebsites.net/api/TravelExpense?account=";
        public static string TravelExpenseUrl { get; set; } = "http://xamarindoggy.azurewebsites.net/api/TravelExpense";
        public static DataService DataService = new DataService();
        public static List<TravelExpense> AllTravelExpense = new List<TravelExpense>();
        public static List<TravelExpensesCategory> AllTravelExpensesCategory = new List<TravelExpensesCategory>();
        public static string Account = "";

        public static 執行功能列舉 正在執行功能 = 執行功能列舉.差旅費用申請;

    }

    public enum 執行功能列舉
    {
        差旅費用申請,
        登出,
    }
}

建立基礎服務與介面和實作

呼叫 Web API 的服務

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Services 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 DataService,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

DataService.cs

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using XFDoggy.Helps;
using XFDoggy.Models;

namespace XFDoggy.Services
{
    public class DataService
    {
        private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        private HttpClient GetClient()
        {
            HttpClient client = new HttpClient(new HttpClientHandler());
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            return client;
        }

        #region TravelExpense
        public async Task<IEnumerable<TravelExpense>> GetTravelExpensesAsync(string account)
        {
            using (HttpClient client = GetClient())
            {
                var fooStr = $"{AppData.TravelExpenseUrl}?account={account}";
                HttpResponseMessage httpResponseMessage = await client.GetAsync(fooStr);
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<IEnumerable<TravelExpense>>(content);
            }
        }

        public async Task PostTravelExpensesAsync(TravelExpense travelExpense)
        {
            using (HttpClient client = GetClient())
            {
                HttpResponseMessage httpResponseMessage = await client.PostAsync(AppData.TravelExpenseUrl,
                new StringContent(
                    JsonConvert.SerializeObject(travelExpense, _jsonSerializerSettings),
                    Encoding.UTF8, "application/json"));
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return;
            }
        }

        public async Task PutTravelExpensesAsync(TravelExpense travelExpense)
        {
            using (HttpClient client = GetClient())
            {
                HttpResponseMessage httpResponseMessage = await client.PutAsync(AppData.TravelExpenseUrl,
                new StringContent(
                    JsonConvert.SerializeObject(travelExpense, _jsonSerializerSettings),
                    Encoding.UTF8, "application/json"));
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return;
            }
        }

        public async Task DeleteTravelExpensesAsync(int id)
        {
            using (HttpClient client = GetClient())
            {
                HttpResponseMessage httpResponseMessage = await client.DeleteAsync($"{AppData.TravelExpenseUrl}?id={id}");
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return;
            }
        }

        #endregion

        #region TravelExpensesCategory
        public async Task<IEnumerable<TravelExpensesCategory>> GetTravelExpensesCategoryAsync()
        {
            using (HttpClient client = GetClient())
            {
                HttpResponseMessage httpResponseMessage = await client.GetAsync(AppData.TravelExpensesCategoryUrl);
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<IEnumerable<TravelExpensesCategory>>(content);
            }
        }

        #endregion

        #region User
        public async Task<AuthUserResult> AuthUserAsync(AuthUser authUser)
        {
            using (HttpClient client = GetClient())
            {
                HttpResponseMessage httpResponseMessage = await client.PostAsync(AppData.UserAuthUrl,
                new StringContent(
                    JsonConvert.SerializeObject(authUser, _jsonSerializerSettings),
                    Encoding.UTF8, "application/json"));
                httpResponseMessage.EnsureSuccessStatusCode();
                string content = await httpResponseMessage.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<AuthUserResult>(content);
            }
        }
        #endregion
    }
}

Prism 事件服務使用類別

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Infrastructure 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 CRUDEvent,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

CRUDEvent.cs

using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Infrastructure
{
    public class CRUDEvent : PubSubEvent<string>
    {
    }
}

取得是否在 Debug 除錯模式下的介面

  1. 在核心PCL XFDoggy 專案內,使用滑鼠右鍵點選 Infrastructure 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 IDebugMode,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

IDebugMode.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XFDoggy.Infrastructure
{
    public interface IDebugMode
    {
        bool IsDebugMode();
    }
}

Android 平台實作 是否在 Debug 除錯模式下 功能

  1. 在 XFDoggy.Droid 專案內,使用滑鼠右鍵點選 Infrastructure 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > Class
  3. 在底下名稱欄位內,輸入 DebugMode,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

DebugMode.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using XFDoggy.Droid.Infrastructure;
using XFDoggy.Infrastructure;

[assembly: Xamarin.Forms.Dependency(typeof(DebugMode))]
namespace XFDoggy.Droid.Infrastructure
{
    public class DebugMode : IDebugMode
    {
        public bool IsDebugMode()
        {
#if DEBUG
            return true;
#else
            return false;
#endif
        }
    }
}

iOS 平台實作 是否在 Debug 除錯模式下 功能

  1. 在 XFDoggy.iOS 專案內,使用滑鼠右鍵點選 Infrastructure 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Apple > Class
  3. 在底下名稱欄位內,輸入 DebugMode,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

DebugMode.cs

using XFDoggy.Infrastructure;
using XFDoggy.iOS.Infrastructure;

[assembly: Xamarin.Forms.Dependency(typeof(DebugMode))]
namespace XFDoggy.iOS.Infrastructure
{
    public class DebugMode : IDebugMode
    {
        public bool IsDebugMode()
        {
#if DEBUG
            return true;
#else
            return false;
#endif
        }
    }
}

UWP 平台實作 是否在 Debug 除錯模式下 功能

  1. 在 XFDoggy.UWP 專案內,使用滑鼠右鍵點選 Infrastructure 資料夾,接著,選擇 加入 > 類別
  2. 在 加入新項目 - XFDoggy 對話窗中,點選 Visual C# > 類別
  3. 在底下名稱欄位內,輸入 DebugMode,接著,點選 新增 按鈕
  4. 使用底下程式碼替換掉剛剛產生的檔案內容

DebugMode.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XFDoggy.Infrastructure;
using XFDoggy.UWP.Infrastructure;

[assembly: Xamarin.Forms.Dependency(typeof(DebugMode))]
namespace XFDoggy.UWP.Infrastructure
{
    class DebugMode : IDebugMode
    {
        public bool IsDebugMode()
        {
#if DEBUG
            return true;
#else
            return false;
#endif
        }
    }
}

建立全域XAML樣式

修改 App.xaml 之 XAML 樣式定義

  1. 在核心PCL XFDoggy 專案內,開啟 App.xaml 檔案
  2. 使用底下 XAML 宣告標記替換掉剛剛開啟的檔案內容

DebugMode.cs

<?xml version="1.0" encoding="utf-8" ?>
<prism:PrismApplication xmlns="http://xamarin.com/schemas/2014/forms"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        xmlns:prism="clr-namespace:Prism.Unity;assembly=Prism.Unity.Forms"
                        x:Class="XFDoggy.App">

  <Application.Resources>
    <!-- Application resource dictionary -->
    <ResourceDictionary>
      <Color x:Key="PageBackgroundColor">#FFEFD4</Color>
      <Color x:Key="ToolbarBackgroundColor">#f08915</Color>
      <Color x:Key="BottomCommandBackgroundColor">#ffcc92</Color>
      <Color x:Key="ButtonTextColor">#fff</Color>
    </ResourceDictionary>
  </Application.Resources>

</prism:PrismApplication>