XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書
顯示具有 Prism 標籤的文章。 顯示所有文章
顯示具有 Prism 標籤的文章。 顯示所有文章

2019/06/18

如何使用 On_PropertyName_Changed 與 附加屬性 Attached Properties 和行為 Behavior,來得知 Entry 與 Editor 已經輸入了多少文字

如何使用 On_PropertyName_Changed 與 附加屬性 Attached Properties 和行為 Behavior,來得知 Entry 與 Editor 已經輸入了多少文字

當在進行 Xamarin.Forms 專案開發的時候,有些時候需要得知 Entry 或者 Editor 這兩種檢視或者稱為控制向,使用者已經輸入了多少內容或者字數,通常可以透過這兩個控制項的 Entry.TextChanged 事件或者 Editor.TextChanged 事件來得知使用者已經輸入了甚麼內容,這樣就可以計算出使用者已經輸入多少文字內容,可是,若要使用事件的話,就需要使用該頁面的 Code Behind 的方式來撰寫 C# 事件委派方法,讓使用者輸入文字的時候,可以觸發這個事件,以便進行計算字數工作。
在使用 Prism 這類 MVVM 開發框架的設計模式的時候,幾乎所有的商業邏輯都會撰寫到 View (頁面) 的 ViewModel (檢視模型) 上,如此,要如何得知使用者已經在 Entry / Editor 檢視中輸入甚麼內容呢?這裡將會提供底下方式來解決此一需求。
這篇文章的範例程式原始碼,可以從 GitHub 取得。

PropertyChanged.Fody 套件提供的 屬性 變更觸發事件

在 PropertyChanged.Fody 的網頁中,將會有一篇關於 On_PropertyName_Changed 文章,告訴 Xamarin.Forms 開發者如何在 ViewModel 中來撰寫出當所綁定的屬性值有異動的時候,將會觸發一個 ViewModel 上的委派方法。
在此應用中,將會在頁面中使用底下 XAML 進行宣告一個 Entry 檢視,其中,當使用者輸入的文字內容,將會自動綁定到 ViewModel 類別內的 C# Property 屬性 EntryChangedInputText 上,而 ViewModel 類別內的 C# Property 屬性 EntryChangedInputTextLength 將會是該輸入文字的字數數值。
xaml
        <Label Text="{Binding EntryChangedInputTextLength}"/>
        <Entry
            Text="{Binding EntryChangedInputText}"/>
現在,請在該頁面的檢視模型 ViewModel 中,定義一個方法,其方法名稱必須為 On屬性名稱Changed ,在這裡將會定義一個 OnEntryChangedInputTextChanged 方法,當這個 Xamarin.Forms 專案執行的時候,使用者在該 Entry 輸入任何文字,將會觸發 OnEntryChangedInputTextChanged 方法執行,在此方法內,將會撰寫符合需求的計算字數商業邏輯程式碼,計算完成之後,就可以儲存到 EntryChangedInputTextLength 屬性內,如此,就可以在螢幕上看到該輸入字數數量了。
        public string EntryChangedInputText { get; set; }
        public int EntryChangedInputTextLength { get; set; } 
        public void OnEntryChangedInputTextChanged()
        {
            if(string.IsNullOrEmpty(EntryChangedInputText))
            {
                EntryChangedInputTextLength = 0;
            }
            else
            {
                EntryChangedInputTextLength = EntryChangedInputText.Length;
            }
        }

使用 Prism 提供的事件 To 命令的行為擴充功能

Prism 這個 MVVM 開發框架,提供了一個 Xamarin.Forms Behavior 行為的物件,其中一個加值行為就是可以設定當某個事件被觸發的時候,需要執行某個命令;如此,使用這個方法將會把相關商業處理邏輯寫道 ViewModel 上,而不在需要撰寫 Code Behind 程式碼了。
首先,請先在該 ContentPage 節點上宣告一個新的命名空間 xmlns:behavior="clr-namespace:Prism.Behaviors;assembly=Prism.Forms" ,這裡將會宣告一個前置詞 Prefix , behavior ,指向 Prims 行為擴充功能組件上,現在,可以在這個頁面上,加入一個 Label 與 Entry,其中 Entry 需要使用 Event.Behaviors 的屬性項目 Property Element 方式,指定新加入的行為物件;這裡將會使用 behavior:EventToCommandBehavior 這個型別,來使用 EventName 這個屬性來指定觸發事件的名稱與 Command 來指定要綁定到 ViewModel 中的一個 DelegateCommand 屬性物件。
xaml
        <Label Text="{Binding EntryBehaviorInputTextLength}"/>
        <Entry
            Text="{Binding EntryBehaviorInputText}">
            <Entry.Behaviors>
                <behavior:EventToCommandBehavior
                    EventName="TextChanged" Command="{Binding EntryChangedCommand}"/>
            </Entry.Behaviors>
        </Entry>
在 ViewModel 內,會在建構函式內建立一個 DelegateCommand 型別的物件到 EntryChangedCommand 屬性上,在建立這個 EntryChangedCommand 屬性的時候,將會傳入一個委派方法,這個委派方法將會用來轉寫計算使用者輸入字數的相關程式碼。
        public string EntryBehaviorInputText { get; set; }
        public int EntryBehaviorInputTextLength { get; set; }
        public DelegateCommand EntryChangedCommand { get; set; }
        public MainPageViewModel(INavigationService navigationService)
        {
            this.navigationService = navigationService;
            EntryChangedCommand = new DelegateCommand(() =>
            {
                EntryBehaviorInputTextLength = EntryBehaviorInputText is null ? 0 : EntryBehaviorInputText.Length;
            });
        }

使用附加屬性來計算使用輸入的文字數量

對於想要針對某個控制項加入可以綁定的屬性,讓 ViewModel 可以根據 View 的屬性異動,進行相關的商業邏輯處理,第一個就是使用原來檢視上的屬性來做處理,若有特殊需求,需要額外的屬性,可以建立一個新類別,繼承原來使用的檢視類別,就可以在這個新控制項中加入一個新的可綁定屬性;第二個方式,就是使用附加屬性,針對想要使用該附加屬性來附加這些附加屬性。
最後一個,就是要建立兩個附加屬性,第一個是 EnableCharCount ,這是用來設定是否要啟用自動計算字數的附加屬性,第二個是 EditorInputTextLength 用來儲存使用者輸入字數的數量值,底下為設計出來的附加屬性 XAML 用法。
由於等下要設計的附加屬性將會限制這兩個附加屬性僅能夠套用到 Entry 或者 Editor 上,當這兩個附加屬性附加到其他檢視的時候,將不會有任何效果的。
這裡有一點要特別注意,對於 CharCountAttachedProperty.CharNumber 這個附加屬性需要在資料綁定延伸標記語法內,要使用 Mode=TwoWay ,這樣才會形成雙向綁定運作方式。
xaml
        <Label Text="{Binding EditorInputTextLength}"/>
        <Label Text="{Binding EntryInputTextLength}"/>
        <Editor
            Text="{Binding EditorInputText}"
            AutoSize="TextChanges"
            local:CharCountAttachedProperty.EnableCharCount="True"
            local:CharCountAttachedProperty.CharNumber="{Binding EditorInputTextLength, Mode=TwoWay}"
            />
        <Entry
            Text="{Binding EntryInputText}"
            local:CharCountAttachedProperty.EnableCharCount="True"
            local:CharCountAttachedProperty.CharNumber="{Binding EntryInputTextLength, Mode=TwoWay}"/>
現在,可以建立一個類別,在此類別上建立兩個附加屬性,在此,建立的類別名稱為 CharCountAttachedProperty,接著,在此類別內,使用程式碼片段 xfAttachedProperty 自動產生附加屬性的相關程式碼。
第一個附加屬性為 EnableCharCountProperty ,在這裡附加屬性將會用來控制是否要進行輸入文字內容的計算工作,在呼叫 BindableProperty.CreateAttached 方法的時候,將會使用 declaringType 來指定這個附加屬性可以附加到那些 XAML 項目上,這裡指定的是 typeof(View),代表任何使用者控制項都可以使用這個附加屬性。
在 EnableCharCountProperty 內最為重要的工作那就是要定義 propertyChanged 這個參數值,傳入一個委派方法 OnEnableCharCountChanged,在此委派方法終將會使用 if (bindable is Entry || bindable is Editor) 來檢查現在該附加屬性是否用在 Entry 或者 Editor 這兩個檢視上,若不是的話,則不會做任何處理。所附加的檢視為 Entry 或者 Editor ,將會檢查是否要啟用這個自動計算字數的屬性值,若為 True,則會訂閱 Entry.TextChanged 事件或者 Editor.TextChanged 事件,否則若為 False,則會取消 TextChanged 的事件訂閱。
記得,當訂閱視覺項目的事件的時候,一定要規劃解除訂閱事件的程式碼,否則,會有可能產生 記憶體遺失 Memory Leak 的問題。
在 OnEntryTextChanged 方法內,將會進行該自動計算使用者輸入文字的字數計算,將結果儲存到 CharNumberProperty 這個附加屬性上。
最後,還是使用相同的程式碼片段, xfAttachedProperty 自動建立 CharNumberProperty 附加屬性程式碼,而在這個 CharNumberProperty 附加屬性上,並不需要加入額外的其他城市碼。
public class CharCountAttachedProperty
{
    #region EnableCharCount 附加屬性 Attached Property
    public static readonly BindableProperty EnableCharCountProperty =
           BindableProperty.CreateAttached(
               propertyName: "EnableCharCount",   // 屬性名稱 
               returnType: typeof(bool), // 回傳類型 
               declaringType: typeof(View), // 宣告類型 
               defaultValue: false, // 預設值 
               propertyChanged: OnEnableCharCountChanged  // 屬性值異動時,要執行的事件委派方法
           );

    public static void SetEnableCharCount(BindableObject bindable, bool entryType)
    {
        bindable.SetValue(EnableCharCountProperty, entryType);
    }
    public static bool GetEnableCharCount(BindableObject bindable)
    {
        return (bool)bindable.GetValue(EnableCharCountProperty);
    }

    private static void OnEnableCharCountChanged(BindableObject bindable, object oldValue, object newValue)
    {
        if (bindable is Entry || bindable is Editor)
        {
            bool isEnable = (bool)newValue;
            if (isEnable)
            {
                if (bindable is Entry)
                {
                    (bindable as Entry).TextChanged += OnEntryTextChanged;
                }
                else if (bindable is Editor)
                {
                    (bindable as Editor).TextChanged += OnEntryTextChanged;
                }
            }
            else
            {
                if (bindable is Entry)
                {
                    (bindable as Entry).TextChanged -= OnEntryTextChanged;
                }
                else if (bindable is Editor)
                {
                    (bindable as Editor).TextChanged -= OnEntryTextChanged;
                }
            }
        }
        else
        {

        }
    }
    #endregion
    private static void OnEntryTextChanged(object sender, TextChangedEventArgs e)
    {
        int foo = CharCountAttachedProperty.GetCharNumber(sender as BindableObject);
        int length = e.NewTextValue.Length;
        CharCountAttachedProperty.SetCharNumber(sender as BindableObject, length);
        (sender as BindableObject).SetValue(CharNumberProperty, length);
        int foo2 = CharCountAttachedProperty.GetCharNumber(sender as BindableObject);
    }

    #region CharNumber 附加屬性 Attached Property
    public static readonly BindableProperty CharNumberProperty =
           BindableProperty.CreateAttached(
               propertyName: "CharNumber",   // 屬性名稱 
               returnType: typeof(int), // 回傳類型 
               declaringType: typeof(View), // 宣告類型 
               defaultValue: 0, // 預設值 
               propertyChanged: OnCharNumberChanged  // 屬性值異動時,要執行的事件委派方法
           );

    public static void SetCharNumber(BindableObject bindable, int entryType)
    {
        bindable.SetValue(CharNumberProperty, entryType);
    }
    public static int GetCharNumber(BindableObject bindable)
    {
        return (int)bindable.GetValue(CharNumberProperty);
    }

    private static void OnCharNumberChanged(BindableObject bindable, object oldValue, object newValue)
    {
    }

    #endregion

}



2019/04/12

Visual Studio 2019 for Xamarin 之安裝與設定 Part5 - 測試與確認開發環境可以進行 Xamarin.Forms 專案開發與結論

Visual Studio 2019 for Xamarin 之安裝與設定 Part5 - 測試與確認開發環境可以進行 Xamarin.Forms 專案開發與結論

Visual Studio 2019 for Xamarin 之安裝與設定 Part5 - 測試與確認開發環境可以進行 Xamarin.Forms 專案開發與結論

對於已經具備擁有 .NET / C# 開發技能的開發者,可以使用 Xamarin.Forms Toolkit 開發工具,便可以立即開發出可以在 Android / iOS 平台上執行的 App;對於要學習如何使用 Xamarin.Forms & XAML 技能,現在已經推出兩本電子書來幫助大家學這這個開發技術。
這兩本電子書內包含了豐富的逐步開發教學內容與相關觀念、各種練習範例,歡迎各位購買。
Xamarin.Forms 電子書
想要購買 Xamarin.Forms 快速上手 電子書,請點選 這裡

想要購買 XAML in Xamarin.Forms 基礎篇 電子書,請點選 這裡

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


您必須要確實進行這些檢查與測試工作,確保您的 Xamarin.Forms 開發環境可以正常運作。
  • 測試可以建立 Xamarin.Forms 專案
  • 建置與執行 Android 專案
  • 建置與執行 iOS 專案
  • 建置與執行 UWP 專案

測試可以建立 Xamarin.Forms 專案

  • 請在開啟 Visual Studio 2019 程式,並且,點選功能表
    檔案 > 新增 > 專案
    Visual Studio 2019 建立新的專案
  • 在 新增專案 對話窗中,請在中間上方的文字輸入盒中輸入 Prism 搜尋出所有與 Prism 有關的專案範本
    在中間選項中,點選 Prism Blank App (Xamarin.Forms),最後點選對話窗右下方的 下一步 按鈕
    新增專案 對話窗
  • 當 設定新的專案 對話窗出現後,在該對話窗的相關欄位,填入適當的文字,最後點選對話窗右下方的 建立 按鈕
    設定新的專案 對話窗
  • 出現了 PRISM PROJECT WIZARD 對話窗
    請依照需求,勾選需要支援的行動狀裝置平台,並且,在下方的 Container 下拉選單欄位,選 Unity
    完成後,請點選該對話窗下方的 CREATE PROJECT 按鈕
    New Cross Platform App 對話窗
  • 此時卻出現了 檢閱方案動作 對話窗,其內容為
    需要 Visual Studio 更新
    下列專案需要平台 SDK (UAP, Version=10.0.16299.0),但其未安裝,或為 Visual Studio 日後更新的一部分
    請安裝平台 SDK,已開啟這些檔案。
    您也可以更新您的專案,指定需要安裝的 SDK:
    Target version: Windows 10, version 1809 (10.0; 組建 17763)
    所以,請點選 安裝 按鈕,進行安裝所需要的 SDK
    New Cross Platform App 對話窗
    此時,Visual Studio 2019 對話窗將會出現,請點選右下方的 安裝 按鈕
    New Cross Platform App 對話窗
    現在,Windows 10 SDK (10.0.16299.0) 將會進行安裝
    New Cross Platform App 對話窗

建置與執行 Android 專案

  • 當 Xamarin.Forms for Prism 專案建立完成後,請使用滑鼠右擊 Android 專案
    選擇 設定為起始專案
    在方案總管中設定預設起始專案
  • 此時,您會在 Visual Studio 2019 中間上方區域,看到 啟動專案已經設定為 Android 專案,並且要執行的裝置為 VS Emulaor 5.2-inch Marshmallow (6.0.0) XXHDPI Phone (Android 6.0 API 23) 這個模擬器
    請點選有綠色三角形的模擬器項目,開始建置與在這個模擬器上來執行
    執行 Android 專案
  • 由於第一次進行專案建置,需要下載許多 NuGet 套件,因此,需要花費一些時間,請耐心等候一下,底下是成功執行完成的畫面
    Xamarin.Forms 的 Android 專案成功執行結果
  • 停止這個 Android 專案的執行 (點選工具列上的紅色正方形按鈕)

建置與執行 iOS 專案

  • 滑鼠右擊 iOS 專案
    選擇 設定為起始專案
  • 建議顯示 iOS 工具列
    請點選功能表 [檢視] > [工具列] ,請勾選 [iOS] 這個功能表項目
    顯示 iOS 輔助工具列圖示
    現在,可以在 Visual Studio 2019 最上方的工具列中,看到 iOS 使用的相關工具圖示
    Pair to Mac 圖示
  • 點選上方圖片中,紅色箭頭指向的圖示, [Pair to Mac - Disconnected]
    當然,這個操作也是可以從功能表中點選 [工具] > [iOS] > [與 Mac 配對]
    從功能表中來啟用 與 Mac 配對 功能
  • 現在 與 Mac 配對 對話窗將會出現
    然而,Visual Studio 將會搜尋網路上是否有可以遠端存取的 Mac 電腦,若有存在的話,該台 Mac 電腦就會出現在清單中
    自動掃描網路並且是有開啟遠端存取的 Mac 電腦
  • 在 Select a Mac 清單內,找到您的 Mac 電腦,並且使用滑鼠雙擊這個項目,此時,將會出現 [連線到 Mac] 對話窗,請在這個對話窗中,輸入遠端登入 Mac 電腦的使用者名稱與密碼,完成後,點選 [Login] 按鈕
    輸入要遠端登入到 Mac 電腦的使用者帳號與密碼
    不過,在這裡強烈建議在 Visual Studio 的 [輸出] 視窗中,切換 [顯示輸出來源] 清單項目成為 [Xamarin],因為,接下來要對遠端 Mac 電腦進行各種登入、更新等動作,都可以在這裡看到相關日誌訊息,最重要的是,當您無法連線到遠端的 Mac 電腦或著覺得連線速度有些緩慢,便可以從這些輸出日誌內容,找到真正發生的原因。
    Windows 電腦與 Mac 電腦存取的日誌
    像是底下的為一個登入 Mac 電腦失敗的情境,在這裡顯示出 嘗試存取通訊端被拒絕,因為存取權限不足 錯誤訊息,此時,可以從 Visual Studio 輸出視窗中,看到更加詳細的資訊。
Checking host configuration for connecting to '李進興的 MacBook Air'...
Checking SSH configuration...
正在檢查可用的磁碟空間...
正在檢查 Mono 安裝...
正在檢查 Xamarin iOS 安裝...
Checking host configuration for connecting to '李進興的 MacBook Air'...
Host '李進興的 MacBook Air' is configured correctly
Starting connection to '李進興的 MacBook Air'...
Starting connection to '李進興的 MacBook Air'...
Starting disconnection from 李進興的 MacBook Air...
Starting disconnection from 李進興的 MacBook Air...
The connection to '李進興的 MacBook Air' has been finished
Couldn't connect to 李進興的 MacBook Air. Please try again.
與 Mac 電腦連線失敗範例
  • 當與遠端 Mac 電腦連線成功之後,工具列上的 [Pair to Mac] 圖示將會變成綠色螢幕,而且在 [與 Mac 配對] 對話窗中,剛剛連線的 Mac 電腦項目的右方,也會出現一個已經連線的圖示,也就是說,現在可以開始建置與執行 iOS 的專案了。
    與 Mac 電腦連線成功的畫面
  • 請點選功能表的 [工具] > [選項],當 選項 對話窗顯示之後,請在左邊清單,展開 [Xamarin] 節點,找到 [iOS 設定] 項目,請確認右方的 [遠端 Simulator 到 Windwos] 選項要有勾選,最後點選右下方的 [確定] 按鈕
    啟用 遠端 Simulator 到 Windwos
  • 請在 Visual Studio 2019 最上方的工具列中,找到 [方案平台] 下拉選項,請在這裡選擇 [iPhoneSimulator] 這個選項,此時,右方下拉選項就會顯示出遠端 Mac 電腦中的各式模擬器清單,選擇一個適合您的模擬器項目,接著點選該項目的綠色按鈕,開始建置與執行 iOS 專案。
    切換使用 iOS 模擬器來進行除錯
  • 底下將會是成功執行 iOS 專案的畫面,也就是說,當要模擬器來進行 iOS 專案執行或除錯的時候,iOS 模擬器將會直接顯示在 Windows 電腦中,如此,就不需要在進行開發過程,同時關注兩個系統螢幕上出現的內容了。
    Xamarin.Forms 的 iOS 專案成功執行結果
  • 停止 iOS 專案的執行

建置與執行 UWP 專案

  • 使用滑鼠右擊 UWP 專案
    選擇 設定為起始專案
  • 點選 Visual Studio 2019 最上方工具列綠色三角形的本機電腦
    底下將會是成功執行 UWP 專案的畫面
    Xamarin.Forms 的 UWP 專案成功執行結果
  • 停止 UWP 專案的執行

結論

若您的 Visual Studio 2019 可以成功建立 Xamarin.Forms 專案,可以建置在 Android / iOS / UWP 平台下執行,那麼,恭喜您,您的 Visual Studio 2019 開發環境,已經可以正常進行 Xamarin.Forms 跨平台專案開發了