XamarinForms 系列課程

特別說明

2018/06/21

Xamarin.Essentials 體驗 5 : Geolocation 地理位置

根據 Xamarin.Essentials 官方文件中指出:Xamarin.Essentials 跨平台應用程式開發介面的開發人員提供他們的行動應用程式。透過 Xamarin.Essentials 的套件幫忙,可以將這些功能整合到您的應用程式:加速計 應用程式資訊 電池 剪貼簿 指南針 資料傳輸 裝置顯示資訊 裝置資訊 電子郵件 檔案系統的協助程式 手電筒 地理編碼 地理位置 迴轉儀 磁力計 開啟瀏覽器 電話撥號員 喜好設定 螢幕鎖定 安全儲存體 SMS 文字轉換語音 追蹤版本 震動。
我們現在來體驗關於 Geolocation 地理位置 這項功能,因此,可以參考底下的專案範例,該專案範例

建立測試專案

  • 首先,我們先使用 Prism Template Pack 擴充功能所提供的專案樣板,建立起一個 Xamarin.Forms 專案,在這裡我們僅選擇 Android / iOS / UWP 類型的專案;接著,我們需要把 PropertyChanged.Fody NuGet 套件安裝到 .NET Standard 專案類別庫內,並且安裝 FodyWeavers.xml 檔案。
  • 緊接著,我們要開始安裝 Xamarin.Essentials NuGet 套件到所有的專案內,在這裡,請使用滑鼠右擊方案節點,選擇 管理方案的 NuGet 套件 選項
  • 請在 NuGet - 解決方案 的視窗中,輸入要搜尋的套件名稱 : Xamarin.Essentials
    並且,請勾選 包括搶鮮版 的文字檢查盒,並且安裝這個套件;我寫這篇文章的時候, Xamarin.Essentials 的最新版本為 0.7.0.17 版本,因此,我們安裝這個版本。
    Xamarin Essentials NuGet Installation
  • 當 Xamarin.Essentials 套件安裝完成之後,您將會發現到在 Visual Studio 2017 的錯誤視窗中,出現了底下錯誤訊息
Warning
偵測到 Xamarin.Android.Support.Compat 的版本衝突。請直接從專案參考套件,以解決此問題。 
 XFESFileSystem.Android -> Xamarin.Essentials 0.7.0.17-preview -> Xamarin.Android.Support.CustomTabs 27.0.2 -> Xamarin.Android.Support.Compat (= 27.0.2) 
 XFESFileSystem.Android -> Xamarin.Android.Support.Design 25.4.0.2 -> Xamarin.Android.Support.Compat (= 25.4.0.2).
偵測到 Xamarin.Android.Support.Compat 的版本衝突
  • Information 這個時候您可以參考 Xamarin.Essentials 體驗 1 : File System Helpers 檔案系統存取 文章中的解決辦法
    完成之後,Android 專案下的 .csproj 檔案,請搜尋這個關鍵字 PackageReference Include="Xamarin.Essentials", 此時,您將會看到底下的內容,安裝了 Xamarin.Android.Support.CustomTabs NuGet 套件,並且都升級到 27.0.2.1 版本
    當然,最快的方式,就是使用 Visual Studio Code 工具,開啟 Android 專案下的 .csproj 檔案,值些修改成為底下內容,儲存後回到 Visual Studio 2017 下,緊接著重新載入這個 .csproj 檔案,就可以進行 Android 專案的編譯動作囉。
XML
    <PackageReference Include="Xamarin.Essentials" Version="0.7.0.17-preview"/>
    <PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="27.0.2.1"/>
    <PackageReference Include="Xamarin.Android.Support.Design" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v4" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="27.0.2.1" />
  • 如此,最初產生的錯誤訊息便會消失了。
  • 由於我們要取得裝置中的 GPS 感應器資料,我們需要在每個原生平台設定啟用這樣使用權限
    首先,請打開 Android 專案內的 MainActivity.cs 檔案
    在 namespace 前面加入底下宣告
[assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
[assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
[assembly: UsesFeature("android.hardware.location", Required = false)]
[assembly: UsesFeature("android.hardware.location.gps", Required = false)]
[assembly: UsesFeature("android.hardware.location.network", Required = false)]
在 iOS 專案下,找到 Info.plist 檔案,使用任何文字編輯器打開這個檔案,加入底下宣告
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>This app needs access location when open.</string>
在 UWP 專案下,找到 Package.appxmanifest 檔案,使用滑鼠雙擊這個檔案,當 Package.appxmanifest 視窗開啟之後,請切換到 功能 標籤頁次,在 功能 清單中,找到 位置 項目,勾選他
Package.appxmanifest
  • 我們將開始要進行 View ViewModel Model 的設計了,首先,我們開啟 MainPage.xaml 這個檔案,底下是我們測試的頁面 XAML 語法
    在這裡,我們將會增加一個 Label 文字控制項,用來顯示抓取到的 GPS 經度 緯度 資訊;另外,有兩個按鈕,一個會開始進行讀取 GPS 經緯度資訊,另外一個是取消抓取經緯度。
    您可以透過 請選擇取得定位位置精確度 Picker 控制項,來選擇要讀取 GPS 經度 緯度 的精確程度。
xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XFESGeolocation.Views.MainPage"
             Title="{Binding Title}">

    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Label Text="{Binding YourLocation}"/>
        <Label Text="GeolocationAccuracy"/>
        <Picker Title="請選擇取得定位位置精確度"
                ItemsSource="{Binding GeolocationAccuracySource}"
                ItemDisplayBinding="{Binding Name}" 
                SelectedItem="{Binding GeolocationAccuracySelected}"/>
        <Button Text="取得定位位置" Command="{Binding GetLocationCommand}"/>
        <Button Text="取消" Command="{Binding CancelLocationCommand}"
                IsVisible="{Binding GetLocation}"/>
    </StackLayout>

</ContentPage>
  • 請打開 MainPageViewModel.cs 這個檔案
    在這個練習範例中,我們將會學習到許多開發技巧,這包括了 非同步工作的取消、選擇器 Picker 控制項的應用、取得 GPS 位置、動態的顯示或隱藏控制項。
    Xamarin.Essentials 套件中的 地理位置 功能,可以使用 Geolocation.GetLocationAsync 這個方法呼叫,若成功執行完畢後,就可以取得 Xamarin.Essentials.Location 類別物件,在這個物件中,透過 Latitude 緯度 / Longtitude 經度 屬性,就可以得知當時裝置所處的 GPS 位置;而我們在呼叫 Geolocation.GetLocationAsync 方法的時候,可以傳入兩個引數:第一個是 GeolocationRequest 用來設定要使用甚麼樣的精確程度來取得 GPS 位置,這個 GeolocationRequest 物件建構的時候,需要提供 GeolocationAccuracy 列舉值,指定 GPS 定位精確度與抓取 GPS 過程的 Timeout 逾期時間;第二個則是 CancellationToken ,這是用來通知非同步工作執行的時候,是否有需要取消此次執行。
    對於要建構的 GeolocationRequest 類別物件的時候,我們將會由使用者來設定 GPS 定位精確度的設定,透過了 資料綁定 Data Binding 機制,我們在 ViewModel 中,可以由 GeolocationAccuracySelected 物件得知該使用者的設定值。
    當使用者按下 取得定位位置 的按鈕,我們會建立一 CancellationTokenSource 物件(要這麼做的原因是,一旦這個物件被使用過後,就無法再度使用取消方法呼叫,因此,我們需要在每次執行的時候,都產生一個這個物件;當取得 CancellationTokenSource 物件之後,我們可以從 CancellationTokenSource.Token 屬性取得這個取消動作的權杖,並且傳入到 GeolocationRequest 建構式內。如此,當我們想要取消 Geolocation.GetLocationAsync 方法的時候,就可以呼叫 CancellationTokenSource.Cancel 方法,一旦呼叫這個方法,且非同步工作尚未執行完成,將會觸發這個非同步工作產生一個例外異常,因此,我們需要在這個非同步呼叫方法,使用 try...catch 將其捕捉是否有任何例外異常產生。
    我們對於第二個按鈕的 IsVisible 屬性,綁定到 ViewModel 中的 GetLocation C# Property 中,因此,若我們想要顯示這個按鈕,只需要在 ViewModel 設定 GetLocation=true;反之,若想要隱藏這個按鈕,我們只需要設定 GetLocation=false。
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XFESGeolocation.ViewModels
{
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Threading;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    using Xamarin.Essentials;

    public class GeolocationAccuracyItem
    {
        public string Name { get; set; }
        public GeolocationAccuracy Item { get; set; }
    }

    public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string YourLocation { get; set; }
        public bool GetLocation { get; set; }
        public DelegateCommand GetLocationCommand { get; set; }
        public DelegateCommand CancelLocationCommand { get; set; }
        private readonly INavigationService _navigationService;
        public CancellationTokenSource CTS { get; set; }
        public CancellationToken Token { get; set; }
        public ObservableCollection<GeolocationAccuracyItem> GeolocationAccuracySource { get; set; } = new ObservableCollection<GeolocationAccuracyItem>();
        public GeolocationAccuracyItem GeolocationAccuracySelected { get; set; }
        public readonly IPageDialogService _dialogService;
        public MainPageViewModel(INavigationService navigationService,
            IPageDialogService dialogService)
        {
            _navigationService = navigationService;
            _dialogService = dialogService;
            GetLocationCommand = new DelegateCommand(async () =>
            {
                if(GeolocationAccuracySelected == null)
                {
                    await _dialogService.DisplayAlertAsync("錯誤", "請選擇GPS定位精確度", "確定");
                    return;
                }
                CTS = new CancellationTokenSource();
                Token = CTS.Token;
                GetLocation = true;

                try
                {
                    var request = new GeolocationRequest(GeolocationAccuracySelected.Item, TimeSpan.FromSeconds(10));
                    var location = await Geolocation.GetLocationAsync(request, Token);

                    if (location != null)
                    {
                        YourLocation = $"Latitude 緯度 : {location.Latitude}, Longitude 經度 : {location.Longitude}";
                    }
                }
                catch (FeatureNotSupportedException fnsEx)
                {
                    // 處理裝置不支援這項功能的例外異常
                }
                catch (PermissionException pEx)
                {
                    // 處理關於權限上的例外異常
                }
                catch (AggregateException ae)
                {
                    // 處理取消的例外異常
                }
                catch (Exception ex)
                {
                    // 無法取得該GPS位置之例外異常
                }

                GetLocation = false;
            });
            CancelLocationCommand = new DelegateCommand(() =>
            {
                GetLocation = false;
                CTS.Cancel();
            });
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
            GeolocationAccuracySource.Clear();
            var fooItems = Enum.GetValues(typeof(GeolocationAccuracy));
            foreach (GeolocationAccuracy item in fooItems)
            {
                GeolocationAccuracySource.Add(new GeolocationAccuracyItem()
                {
                     Name = item.ToString(),
                     Item = item,
                });
            }
        }

    }
}
  • Android 平台執行結果
    這是一開始執行的螢幕截圖
    Xamarin Essentials
    現在,您可以點選 選擇器 控制器,這個時候,就會跳出可以選擇的 GPS 定位清單。
    Xamarin Essentials
    當我們選擇完 GPS 定位精確度之後,便可以按下 取得定位位置 按鈕,此時,您將會看到第二個按鈕顯示在螢幕上了。
    Xamarin Essentials
    由於我們使用模擬器進行測試,抓取 GPS 感應器的速度相當的快速,所以,您沒有機會測試使用 取消 按鈕的機會,不過,若您將這個程式在實體手機上執行的時候,就可以體驗這樣的操作了。
    下圖,是我們抓取到的 GPS 位置結果
    Xamarin Essentials
    想要在 Visual Studio for Android Emulator 中來客製化 GPS 定位位置,可以從該模擬器視窗的左邊,看到有一長條工具列。在這個工具列最下方按鈕 >> ,按下去之後,將會顯示出另外一個視窗。
    Visual Studio for Android Emulator
    在這個視窗中,您可以點選 位置 標籤頁次,使用滑鼠捲動滾輪,便可以縮放地圖,想要把您的 GPS 定位到某個地方,指需要使用滑鼠點選地圖即可。
    Visual Studio for Android Emulator
  • 地理位置精確度
    想要得知不同平台下的地理位置精確度,可以參考 這篇文章



2018/06/20

Xamarin.Essentials 體驗 4 : Clipboard 剪貼簿

根據 Xamarin.Essentials 官方文件中指出:Xamarin.Essentials 跨平台應用程式開發介面的開發人員提供他們的行動應用程式。透過 Xamarin.Essentials 的套件幫忙,可以將這些功能整合到您的應用程式:加速計 應用程式資訊 電池 剪貼簿 指南針 資料傳輸 裝置顯示資訊 裝置資訊 電子郵件 檔案系統的協助程式 手電筒 地理編碼 地理位置 迴轉儀 磁力計 開啟瀏覽器 電話撥號員 喜好設定 螢幕鎖定 安全儲存體 SMS 文字轉換語音 追蹤版本 震動。
我們現在來體驗關於 Clipboard 剪貼簿 這項功能,因此,可以參考底下的專案範例,該專案範例

建立測試專案

  • 首先,我們先使用 Prism Template Pack 擴充功能所提供的專案樣板,建立起一個 Xamarin.Forms 專案,在這裡我們僅選擇 Android / iOS / UWP 類型的專案;接著,我們需要把 PropertyChanged.Fody NuGet 套件安裝到 .NET Standard 專案類別庫內,並且安裝 FodyWeavers.xml 檔案。
  • 緊接著,我們要開始安裝 Xamarin.Essentials NuGet 套件到所有的專案內,在這裡,請使用滑鼠右擊方案節點,選擇 管理方案的 NuGet 套件 選項
  • 請在 NuGet - 解決方案 的視窗中,輸入要搜尋的套件名稱 : Xamarin.Essentials
    並且,請勾選 包括搶鮮版 的文字檢查盒,並且安裝這個套件;我寫這篇文章的時候, Xamarin.Essentials 的最新版本為 0.7.0.17 版本,因此,我們安裝這個版本。
    Xamarin Essentials NuGet Installation
  • 當 Xamarin.Essentials 套件安裝完成之後,您將會發現到在 Visual Studio 2017 的錯誤視窗中,出現了底下錯誤訊息
Warning
偵測到 Xamarin.Android.Support.Compat 的版本衝突。請直接從專案參考套件,以解決此問題。 
 XFESFileSystem.Android -> Xamarin.Essentials 0.7.0.17-preview -> Xamarin.Android.Support.CustomTabs 27.0.2 -> Xamarin.Android.Support.Compat (= 27.0.2) 
 XFESFileSystem.Android -> Xamarin.Android.Support.Design 25.4.0.2 -> Xamarin.Android.Support.Compat (= 25.4.0.2).
偵測到 Xamarin.Android.Support.Compat 的版本衝突
  • Information 這個時候您可以參考 Xamarin.Essentials 體驗 1 : File System Helpers 檔案系統存取 文章中的解決辦法
    完成之後,Android 專案下的 .csproj 檔案,請搜尋這個關鍵字 PackageReference Include="Xamarin.Essentials", 此時,您將會看到底下的內容,安裝了 Xamarin.Android.Support.CustomTabs NuGet 套件,並且都升級到 27.0.2.1 版本
    當然,最快的方式,就是使用 Visual Studio Code 工具,開啟 Android 專案下的 .csproj 檔案,值些修改成為底下內容,儲存後回到 Visual Studio 2017 下,緊接著重新載入這個 .csproj 檔案,就可以進行 Android 專案的編譯動作囉。
XML
    <PackageReference Include="Xamarin.Essentials" Version="0.7.0.17-preview"/>
    <PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="27.0.2.1"/>
    <PackageReference Include="Xamarin.Android.Support.Design" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v4" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="27.0.2.1" />
    <PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="27.0.2.1" />
  • 如此,最初產生的錯誤訊息便會消失了。
  • 我們需要安裝 Toasts.Forms.Plugin NuGet 套件到 Xamarin.Forms 專案 (也就是 .NET Standard 專案) 內,這是因為我們需要能夠使用 Toast 快顯通知這樣功能,顯示出一些訊息到螢幕上。
  • 一旦您安裝好 Toasts.Forms.Plugin NuGet 套件後,您需要在每個原生專案內進行該套件初始化的設定與相依性注入的設定,在這裡,我們將會使用 Prism 所提供的相依性注入容器服務,而不會使用 Xamarin.Forms 預設的相依性注入服務。只要經過了這樣處理程序之後,我們就可以在 Xamarin.Forms 的 ViewModel 中,隨時使用快顯通知 Toast 這樣好用的介面功能了。
  • 請打開 Android 專案的 MainActivity.cs 這個檔案
    我們要在 OnCreate 這個方法內,加入這個套件初始化的呼叫
    Plugin.Toasts.ToastNotification.Init(this);
    另外,我們也需要進行這個 抽象介面 Plugin.Toasts.IToastNotificator 與具體實作類別 Plugin.Toasts.ToastNotification 的註冊,請在這個檔案中找到 RegisterTypes 方法,在這個方法內填入 container.Register();
C#
using Android.App;
using Android.Content.PM;
using Android.OS;
using Prism;
using Prism.Ioc;

namespace XFESClipboard.Droid
{
    [Activity(Label = "XFESClipboard", Icon = "@mipmap/ic_launcher", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            Plugin.Toasts.ToastNotification.Init(this);

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App(new AndroidInitializer()));
        }
    }

    public class AndroidInitializer : IPlatformInitializer
    {
        public void RegisterTypes(IContainerRegistry container)
        {
            // Register any platform specific implementations
            container.Register<Plugin.Toasts.IToastNotificator, Plugin.Toasts.ToastNotification>();
        }
    }
}
  • 請打開 iOS 專案的 AppDelegate.cs 這個檔案
    我們要在 FinishedLaunching 這個方法內,加入這個套件初始化的呼叫
    Plugin.Toasts.ToastNotification.Init();
    另外,我們也需要進行這個 抽象介面 Plugin.Toasts.IToastNotificator 與具體實作類別 Plugin.Toasts.ToastNotification 的註冊,請在這個檔案中找到 RegisterTypes 方法,在這個方法內填入 container.Register();
C#
using Foundation;
using Prism;
using Prism.Ioc;
using UIKit;


namespace XFESClipboard.iOS
{
    // 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 : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        //
        // 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)
        {
            Plugin.Toasts.ToastNotification.Init();
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App(new iOSInitializer()));

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

    public class iOSInitializer : IPlatformInitializer
    {
        public void RegisterTypes(IContainerRegistry container)
        {
            container.Register<Plugin.Toasts.IToastNotificator, Plugin.Toasts.ToastNotification>();
        }
    }
}
  • 請打開 UWP 專案的 MainPage.xaml.cs 這個檔案 (請特別注意,不是 Xamarin.Forms 專案內的 MainPage.xaml.cs 喔)
    我們要在 MainPage 建構式 這個方法內,加入這個套件初始化的呼叫
    Plugin.Toasts.UWP.ToastNotification.Init();
    另外,我們也需要進行這個 抽象介面 Plugin.Toasts.IToastNotificator 與具體實作類別 Plugin.Toasts.ToastNotification 的註冊,請在這個檔案中找到 RegisterTypes 方法,在這個方法內填入 container.Register();
C#
using Prism;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace XFESClipboard.UWP
{
    public sealed partial class MainPage
    {
        public MainPage()
        {
            this.InitializeComponent();

            Plugin.Toasts.UWP.ToastNotification.Init();

            LoadApplication(new XFESClipboard.App(new UwpInitializer()));
        }
    }

    public class UwpInitializer : IPlatformInitializer
    {
        public void RegisterTypes(IContainerRegistry container)
        {
            container.Register<Plugin.Toasts.IToastNotificator, Plugin.Toasts.UWP.ToastNotification>();
        }
    }
}
  • 我們將開始要進行 View ViewModel Model 的設計了,首先,我們開啟 MainPage.xaml 這個檔案,底下是我們測試的頁面 XAML 語法
    在這裡,我們將會增加一個文字輸入盒,讓使用者可以使用剪貼簿內的內容,貼到這個控制項內,另外,我們會在第一個 Label 控制項內加入手勢操作的 TapGestureRecognizer ,這使得使用點選這串文字之後,將會把這個顯示的文字內容,放入剪貼簿上。
    除了可以讓使用者使用手勢操作來執行剪貼簿的運算功能,也可以使用最後一個按鈕,當使用者按下這個按鈕後,便會由程式從剪貼簿上取回文字,放到文字輸入盒內。
xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XFESClipboard.Views.MainPage"
             Title="Clipboard 剪貼簿">

    <StackLayout HorizontalOptions="Fill" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" >
            <Label.GestureRecognizers>
                <TapGestureRecognizer Command="{Binding LabelTapCommand}"
                                      CommandParameter="Welcome to Xamarin Forms and Prism!"/>
            </Label.GestureRecognizers>
        </Label>
        <Entry Text="{Binding MyEntry}"/>
        <Button Text="取出剪貼簿內文字" Command="{Binding RetriveClipboardCommand}"/>
    </StackLayout>

</ContentPage>
  • 請打開 MainPageViewModel.cs 這個檔案
    想要把文字放到剪貼簿上,我們僅需要呼叫這個方法
    Clipboard.SetText
    若要在程式內取回剪貼簿的內容,我們會使用 Clipboard.HasText 屬性檢查剪貼簿內是否有內容,若有內容,我們可以使用方法
    await Clipboard.GetTextAsync()
    將剪貼簿的文字內容取出來
using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XFESClipboard.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    using Xamarin.Essentials;

    public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string MyEntry { get; set; }
        public DelegateCommand<string> LabelTapCommand { get; set; }
        public DelegateCommand RetriveClipboardCommand { get; set; }
        private readonly INavigationService _navigationService;
        public Plugin.Toasts.IToastNotificator _ToastNotificator { get; set; }
        public MainPageViewModel(INavigationService navigationService,
            Plugin.Toasts.IToastNotificator toastNotificator)
        {
            _navigationService = navigationService;
            _ToastNotificator = toastNotificator;

            LabelTapCommand = new DelegateCommand<string>(async (x) =>
            {
                Clipboard.SetText(x);
                await _ToastNotificator.Notify(new Plugin.Toasts.NotificationOptions()
                {
                    Title = $"通知",
                    Description = $"{MyEntry} 已經複製到剪貼簿中"
                });
            });

            RetriveClipboardCommand = new DelegateCommand(async () =>
            {
                if( Clipboard.HasText )
                {
                    MyEntry = $"產生自剪貼簿:{await Clipboard.GetTextAsync()}";
                }
                else
                {
                    await _ToastNotificator.Notify(new Plugin.Toasts.NotificationOptions()
                    {
                        Title = $"警告",
                        Description = $"剪貼簿內沒有任何資料"
                    });
                }
            });
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {
        }

    }
}
  • Android 平台執行結果
    這是一開始執行的螢幕截圖
    Xamarin Essentials
    現在,因為剪貼簿內現在沒有任何內容,所以,當我按下按鈕之後,會得知剪貼簿內沒有任何資料可以使用。
    Xamarin Essentials
    讓我們按下螢幕上的 Welcome to Xamarin Forms and Prism! 文字之後,便會將這個文字儲存到剪貼簿上。
    Xamarin Essentials
    我們可以在文字輸入盒中長按,此時,會出現一個彈出功能選項,讓我們點選 PASTE 貼上 這個選項。
    Xamarin Essentials
    如此,便可以從剪貼簿中將文字取出來,設定到文字輸入盒內。
    Xamarin Essentials
    若我們再度按下按鈕,現在剪貼簿中有內容了,所以,我們可以將剪貼簿內的文字取出來,設定到文字輸入盒內。
    Xamarin Essentials