XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2017/01/15

Xamarin FAQ 1-14 : 如何從子頁面傳遞物件到父頁面

問題

當在一個子頁面是從父頁面導航過來的,不過,往往會有機會遇到這樣的情況,當從子頁面返回到父頁面的時候,需要把子頁面的一些狀態或者物件,傳回到父頁面中;所以,當回到父頁面的時候,就可以更新到最新的狀態。
+

解答

在使用 Prism 設計框架工具,我們可以使用事件聚合器 (Event Aggregator)來解決這樣的問題,在父頁面中,使用事件聚合器來訂閱這類事件,當在子頁面要回到父頁面的時候,可以透過事件聚合器發佈一個訊息,讓父頁面可以來處理。

2017/01/14

Xamarin FAQ 1-13 : 如何從父頁面傳遞物件到子頁面

問題

在進行導航頁面型態的應用程式開發的時候,經常會處理,當開啟一個新網頁的時候,需要傳遞一些物件到新頁面內,讓新頁面根據傳遞進來的物件,做出不同的處理動作。

解答

在導航物件的 NavigateAsync 方法內,可以接受 NavigationParameters 物件,這個物件的型別為 Dictionary<string, object>,因此,您可以透過 NavigationParameters 物件傳遞很多的物件到新(子)頁面內。
底下為 NavigateAsync 的方法簽章 Method Signature
        //
        // 摘要:
        //     Initiates navigation to the target specified by the name.
        //
        // 參數:
        //   name:
        //     The name of the target to navigate to.
        //
        //   parameters:
        //     The navigation parameters
        //
        //   useModalNavigation:
        //     If true uses PopModalAsync, if false uses PopAsync
        //
        //   animated:
        //     If true the transition is animated, if false there is no animation on transition.
        Task NavigateAsync(string name, NavigationParameters parameters = null, bool? useModalNavigation = default(bool?), bool animated = true);

2017/01/13

Xamarin FAQ 1-12 : 使用簡單的方式來保存應用程式的狀態

問題

開發一個行動裝置應用程式,一定會用到這樣的需求,那就是需要把應用程式執行的某些狀態,儲存到手機永久儲存體中,等到下次應用程式再度啟動時候,需要把當時的狀態從手機中的永久儲存體讀取出來,並且重新記錄到應用程式內的 .NET 物件內。

解答

在 Xamarin.Fomrs 應用程式中,有個 Application 類別有個靜態物件,表示 Xamarin.Forms 這個應用程式的當時的應用程式物件,您可以透過 Application.Current 取得正在執行的 Application 類別物件。
在 Application 實例物件中,有個 Properties 屬性,這個屬性的型別是 IDictionary<string, object>,因此,您可以將任何型態的物件值儲存到 Application.Current.Properties 這個實例中。一旦,您將系統內的某個物件加入到 Application.Current.Properties 這個實例內,系統會自動將其儲存到行動裝置內的永久儲存體內。
不過,您需要特別注意到一件事情,Properties 這個字典型別,僅僅能夠序列化基本類型(Primitive Type)的物件,所以,不太建議使用 Properties 來儲存太複雜的物件內容。

2017/01/12

Xamarin FAQ 1-11 : 如何指定顯示頁面每次都要執行的工作

問題

往往當需要顯示一個新的頁面的時候,可能會接收來自其他頁面所傳送出來的參數並且根據這些參數進行準備這個頁面要顯示的資料,但是,很多時候,要準備的資料可能會來自於檔案系統內的檔案、網路上的 Web API等等,這些進行頁面資料初始化的動作時候,很多需要滿多的時間來進行執行,如何進行這樣的工作設計呢?

解答

很多人會把頁面資料初始化的工作,都放在建構式內,但是,這樣會產生一個問題,那就是當這個頁面物件要建立起來的時候,會花費較多的時間,這將會導致當要切換到新頁面的時候,可能需要等候一段時間,才能夠看到新的頁面出現,這樣的設計方式,會造成使用者以為應用程式有嚴重延遲特性,這是一個不是很好的設計方式。
有人會在建構式內放入 await 的非同步的呼叫方法,這樣的作法不被 C# 所允許的。
在這裡有兩個方式可以來處理這樣的情況,在底下的方法都是透過事件呼叫的方式來處理,因此,您可以在這裡使用 Async / Await 的非同步呼叫方法。
  • 使用每個頁面檢視的 call behind OnAppearing() 方法
        protected override void OnAppearing()
        {
            base.OnAppearing();
        }
  • 另外一種作法,那就是在檢視模型 ViewModel 內的 OnNavigatedFrom / OnNavigatedTo,如此,
        public void OnNavigatedFrom(NavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            Init();
        }

2017/01/11

Xamarin FAQ 1-10 : Visual Studio Emulator for Android 疑難排解

問題

當您使用 Visual Studio 開發 Android 應用程式的時候,往往會遇到 Visual Studio Emulator for Android 無法啟動、啟動後無法正常運作、無法進行除錯、一執行程式就閃退、無法抓到模擬器、無法正常下載新的模擬器、無法使用 Google Play 服務等等,造成剛開始想要學習開發 Xamarin.Forms 的開發者莫大的困擾,那要如何解決這些問題呢?

解答

Microsoft 微軟已經幫您準備好了這些相關問題的解答,請參考這篇文章 Visual Studio Emulator for Android 疑難排解 與 Visual Studio 2015 Android 模擬器

底下為這些文章的主題

開始之前
無法安裝模擬器
無法連接到網域或公司網路上的網路目的地
當網路設定需要手動進行時,無法連接到網路目的地
模擬器啟動很慢、因逾時而無法啟動,或應用程式部署失敗
模擬器無法啟動
無法啟動模擬器 (第一次使用)
安裝模擬器後無法啟動電腦
Visual Studio 在嘗試將應用程式部署至模擬器時遇遭困難,或模擬器未作為偵錯目標出現在其他 IDE 中
模擬器因為無法設定 UDP 連接埠而停止回應
模擬器無法執行使用 Google Play 服務的應用程式
無法拖放檔案、APK 或可刷新的 zip 檔案
螢幕擷取畫面的解析度不正確
模擬器無法轉譯 OpenGL 內容
模擬器未回應多點觸控筆勢
支援資源

2017/01/10

使用 Xamarin.Forms 進行專案開發,必備哪些基本技能

當您使用 Xamarin.Forms 進行專案開發的時候,有哪些基本技能要熟悉呢?您都學會了嗎?
C# / .NET
XAML語法
XAML標記延伸功能
各種不同螢幕規格的視覺設計
Data Binding
應用程式生命週期
各種頁面
不同版面配置
使用者介面控制項
使用者控制項宣告與使用
降低部署檔案大小
程式碼簽名
在模擬器與實機測試
問題除錯技巧
使用者介面自動測試
呼叫 Web API

Xamarin FAQ 1-09 : 開發 Xamarin.Forms 建議的開發配備

問題

開發跨平台的原生應用程式 (Native App),勢必要考慮到各種行動裝置的開發與測試情境,採用模擬器來測試原生應用程式是最常見的作法。當您選擇 Xamarin.Forms 來建置 App 時,最讓人頭疼的就是架設好完整的開發環境,然而跨平台的 App 會牽涉到許多平台上的限制,對於軟硬體配備的選擇就是一門大學問,那麼想要開發 Xamarin.Forms 的應用程式,要如何準備相關的軟硬體環境呢?
+

解答

開發跨平台的原生應用程式 (Native App),勢必要考慮到各種行動裝置的開發與測試情境,採用模擬器來測試原生應用程式是最常見的作法。當您選擇 Xamarin.Forms 來建置 App 時,最讓人頭疼的就是架設好完整的開發環境,然而跨平台的 App 會牽涉到許多平台上的限制,對於軟硬體配備的選擇就是一門大學問,本篇文章將說明在不同需求下需要考量的軟硬體配置。

電腦與作業系統需求

Mac OS X

  • 作業系統需求:Mac OS X Yosemite(10.10) 或者以上版本
  • 需要安裝最新版本的 Xcode 與 iOS SDK ( 可以從 iOS Developer Center 來下載 )
  • 安裝最新版本的 Xamarin Studio ( 可以從 這裡 來下載 )

Windows

  • 作業系統需求:Windows 10 Professional
  • 需要安裝 Hyper-V 服務
  • 安裝 Visual Studio 2015 ( 可以從 這裡 來下載 )

開發工具需求

透過 Xamarin.Forms 來開發跨平台的原生應用程式 (Native App),在不同的作業系統與整合開發環境 IDE 工具能夠產生出不同類型的原生應用程式,目前有以下兩個 IDE 工具可選:

Visual Studio 2015 (只能執行在 Windows 上面)

  • 可以開發、建置原生 Android / UWP 應用程式。
  • 安裝時,請記得要勾選 Android 原生開發套件(SDK) 與 通用應用程式開發工具 (UWP SDK) 安裝到您的電腦下。

Xamarin Studio (只能執行在 Mac 電腦上)

  • 可以開發、建置原生 Android / iOS 應用程式。
  • 您必須額外安裝 iOS SDK & Xcode 等工具程式。
簡單來說,你沒辦法透過 Mac 電腦產生出 UWP 應用程式,也沒辦法單純只用 Windows 電腦產生出 iOS 應用程式。
若您想同時開發出 iOS / Android / UWP 等跨平台應用程式,你必須至少準備兩台電腦才有辦法建置出完整的跨平台應用程式。

常見問題解答

  1. 我可否在 Mac OS X 上面安裝虛擬機器,並且在 VM 中跑 Windows 作業系統,這樣我可以用一台 Mac 電腦進行跨平台應用程式開發嗎?
    Windows 10 Mobile 模擬器需要 Hyper-V 服務才能夠運行,因此,若在 Mac OS X 上的 Parallels Desktop Pro 有支援 nested virtualization,因此開 Windows 10 Mobile 模擬器上安裝虛擬機器,並且在 VM 中跑 Windows 作業系統(感謝 Yu-Hsin Hung 幫忙修正)。
  2. 當 Android & iOS 有最新的SDK推出,Xamarin 何時可以支援這些最新的 SDK?
    對於有新版本的 Android & iOS 推出後,根據以往經驗,最多 2~7天,Xamarin 就會推出相對應的更新,讓您可以使用這些最新的 SDK 來開發這些應用程式。
  3. 當我選擇使用 Xamarin,我的應用程式有多少比例使用 C# 撰寫出來?
    您的應用程式將會 100% 都使用 C# 來撰寫並開發出來,這包含了 UI、商業邏輯。
  4. 在進行 Xamarin.Forms 應用程式開發時候,我可以使用第三方的 .NET 程式庫嗎?
    是的,例如,您可以使用 Json.NET NuGet 套件在 PCL 專案上或者使用在各個原生專案上。
  5. 當我在 Windows 作業系統的 Visual Studio 2015 開發 Xamarin.Forms 應用程式,卻無法透過 Xamarin Mac Agent 與遠端 Mac電腦連線?
    您需要在 Mac 電腦上啟用 遠端登入 功能,並且設定相關帳號可以使用遠端登入功能;若還是不行,請確認 Mac 電腦上沒有做 SSH ( 22 Port)的阻擋。您可以在 Windows 作業系統上,使用類似 Putty 這裡終端機連線工具,設定使用 SSH 方式連線到 Mac 電腦來進行測試。
  6. 我使用 Xamarin.Forms 進行開發跨平台應用程式,我還需要學習個平台的 UI 定義與設計方法嗎?
    若您採用 Xamarin.Forms 進行開發跨平台應用程式,所有的頁面 UI 都會透過 XAML 標記宣告語言來定義;因此,您不再需要學習 Android 的 XML UI定義與 iOS 的 Storyboard。
  7. 當我使用 Visual Studio 開發 Xamarin.Froms 應用程式,我可以在 Windows 系統上看到 iOS 模擬器嗎?
    當然可以,若您使用 Visual Studio 開發 Xamarin.Forms應用程式,可以同時看到與操作 Android, iOS, Windows 10 Mobile 的模擬器;若您想要在 Windows 作業系統上使用 iOS 模擬器,請安裝 iOS Simulator (for Windows)
  8. 哪個 Visual Studio 2015 版本支援 Xamarin.Forms 的應用程式開發
    全系列的 Visual Studio 2015 都可以開發 Xamarin.Forms 的應用程式,包含 Visual Studio 2015 社群版本。
  9. 由於 Xamarin.Forms 程式會在 PCL 專案內開發,我可以在 PCL 專案內呼叫原生(Android/iOS/UWP)專案內的各項功能嗎?(例如:拍照、GPS定位等等)
    這絕對是沒有問題,您可以透過插件 (Plug-ins)或者 Xamarin.Forms 內建的相依性服務功能,來做到這些需求。
  10. 想要使用 Xamarin.Forms 開發應用程式,有哪些技術項目是要學的?
    只要您精通 C# / XAML / MVVM 這些觀念與技巧,就可以快速開發出容易維護與高效能的原生應用程式。
  11. 我可以針對特定平台的 UI 進行客製化設計,例如:在 Android 平台中的文字輸入盒,可以有四週框線?
    完全沒有問題,您可以透過 UI Renderer 技術,針對不同平台來客製化 UI 要顯示成為甚麼樣貌。
  12. Xamarin.Forms 有支援 UI 自動測試功能嗎? 
    您可以使用 Xamarin.UITest 來撰寫 UI 自動測試的程序,並且透過 Xamarin 提供的 Test Cloue,將您的應用程式一次佈署不同的實體使用上,得到在不同手機上的測試結果與當時的螢幕截圖。注意,這項服務需要另外付費
  13. 哪些種類的應用程式,不適合使用 Xamarin.Forms 方式來進行開發。
    具有豐富變化的UI設計(例如 Game)、需要使用大量原生平台專屬 API (大量地圖方面的應用)、多媒體應用程式(AR / VR)、客製UI比起共用程式碼來的重要的應用程式(每個平台,需要大量客製化不同樣貌的UI)

2017/01/09

Xamarin FAQ 1-08 : 在巢狀虛擬化的虛擬機器中執行 Hyper-V

問題

若您需要在 Hyper-V 內,再度開啟一個 Hyper-V 的 VM,例如,在您的 Hyper-V VM 內,建立另外一個 Win10 系統並且安裝的 Visual Studio 2015 與 Xamarin Toolkit,此時,若您想要在 VM 內開啟 Visual Studio,接著進行 Xamarin.Forms 的專案開發與在模擬器上測試;這個時候,您就需要使用巢狀虛擬化的功能,否則,您的 Android 模擬器就會開不起來。

解答

  • 請開啟 命令提示字元 視窗
  • 輸入 powershell 並且按下 Enter,進入到 powershell
    +
  • 輸入 Set-VMProcessor -VMName "你的虛擬機器名稱" -ExposeVirtualizationExtensions $true

2017/01/08

用 Xamarin.Forms 開發拍照與上傳照片的功能

這是有人提出的問題,想要使用 Visual Studio + Xamarin.Forms,開發出一個可以使用手機拍照的功能,並且可以將這個照片檔案,上傳到網路上;我剛剛寫了一個小的範例程式,底下的程式碼為這個拍照頁面的 ViewModel 程式碼。

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式

想要使用拍照功能,您需要安裝這兩個 PCLStorage / Xam.Plugin.Media NuGet 套件。
其中,要進行拍照的時候,可以使用這個方法 CrossMedia.Current.TakePhotoAsync 來啟動手機中的照相機,一旦完成照相作業,就可以取得這個照片的檔案路徑。
而要將圖片上傳到遠端伺服器的工作,則使用了 .NET 裡面的 HttpClient 物件,當然,在 PCL 專案內您會找不到這個類別,請您要安裝 Microsoft.Net.Http 這個 NuGet 套件即可使用。
        public MainPageViewModel(IPageDialogService dialogService)
        {

            _dialogService = dialogService;
            拍照Command = new DelegateCommand(async () =>
            {
                // 進行 Plugin.Media 套件的初始化動作
                await CrossMedia.Current.Initialize();

                // 確認這個裝置是否具有拍照的功能
                if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
                {
                    await _dialogService.DisplayAlertAsync("No Camera", ":( No camera available.", "OK");
                    return;
                }

                // 啟動拍照功能,並且儲存到指定的路徑與檔案中
                var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
                {
                    Directory = "Sample",
                    Name = "Sample.jpg"
                });

                if (file == null)
                    return;

                // 讀取剛剛拍照的檔案內容,轉換成為 ImageSource,如此,就可以顯示到螢幕上了
                MyImageSource = ImageSource.FromStream(() =>
                {
                    var stream = file.GetStream();
                    return stream;
                });

                #region 將剛剛拍照的檔案,上傳到網路伺服器上
                using (var client = new HttpClient())
                {
                    using (var content = new MultipartFormDataContent())
                    {
                        // 取得這個圖片檔案的完整路徑
                        var path = file.Path;
                        // 取得這個檔案的最終檔案名稱
                        var filename = Path.GetFileName(path);

                        // 開啟這個圖片檔案,並且讀取其內容
                        using (var fs = file.GetStream())
                        {
                            var streamContent = new StreamContent(fs);
                            streamContent.Headers.Add("Content-Type", "application/octet-stream");
                            streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
                            content.Add(streamContent, "file", filename);

                            // 上傳到遠端伺服器上
                            HttpResponseMessage message = await client.PostAsync("http://YourHost/api/UploadImage", content);
                            var input = message.Content.ReadAsStringAsync();
                            // 更新頁面上的 Image 控制項,顯示出剛剛上傳的圖片內容
                            RemoteImageURL = $"http://YourHost/uploads/{filename}";
                        }
                    }
                }
                #endregion

            });
        }

Xamarin FAQ 1-007 : 如何清除導航堆疊 (Navigation Stack)

問題

根據當時應用程式的操作流程,會需要轉跳到某個頁面,此時,螢幕上不會有回上一頁的導航按鈕出現,必且,手機的實體回上一頁按鍵,當您按下之後,這個應用程式就會直些回到手機桌面,並不會跳到之前來的頁面。最經典的使用案例那就是,使用者可以在應用程式的任何地方,點選 登出 功能選項,接著,應用程式就會跳到 登入 頁面上,此時,這個頁面就會成為這個應用程式的首頁,因為導航堆疊已經被清空了,所以,當按下實體按鍵的回上一頁按鈕,此時,應用程式也就回到背景模式,手機桌面也就出現了。

解答

想要解決這個問題,可以使用底下程式碼
        public YourConstructor(INavigationService navigationService)
        {
            _navigationService = navigationService;
            登出Command = new DelegateCommand(() =>
            {
                await _navigationService.NavigateAsync("xf:///MDPage/NaviPage/LoginPage");
            });
        }|
在這個範例程式碼中,當您需要導航到 登入 頁面的時候 (LoginPage),請使用絕對路徑的 URI 來表示,而不要使用相對路徑,例如:await _navigationService.NavigateAsync("LoginPage");,如此,當切換到 登入 頁面之後,應用程式的導航堆疊也就清空了。