XamarinForms ContentView Binding

XamarinForms自訂控制項

張阿鬼 2017/12/18 08:14:17
621

XamarinForms自訂控制項


簡介

如何在Xamarin Forms中建立自訂控制項

作者

張朝銘


1.前言

l   本文件用來提供Xamrin Forms開發人員開發控制項應用

l   開發工具使用Visual Studio 2017

l   適合Xamarin Forms進階開發者


2.目的

 Xamarin Forms中建立可重複使用的使用者控制項

3.本文

APP開發時,常會有某部分的控制項組合會重複的出現在許多頁面上,僅只有呈現的資料或者觸發的邏輯不同,這時我們可建立使用者控制項ContentView來將這些控制項進行包裝。

3.1建立ContentView

 首先在XamarinForms專案上加入新增項目,選擇Content View

 假設以下畫面中的輸入框與按鈕的組合是我們要變為自訂控制項的部分

接著在剛剛建立出來的ContentView中,加入以下內XAML內容:

  <?xml version="1.0" encoding="UTF-8"?>

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             x:Class="XamarinFormsCustomView.MyView">

    <StackLayout Orientation="Horizontal" >

        <Entry x:Name="entry" HorizontalOptions="FillAndExpand"/>

        <Button x:Name="btn" Text="Test" />

    </StackLayout>

</ContentView>

3.2引用控制項與建立自訂屬性、事件

建立完ContentView後,接著就是要在原本的Page頁面上引用該控制項,因控制項是建立在專案本身,所以在Page上要記得先宣告一下。

透過在Page宣告的前置詞引用該控制項。

 

    <StackLayout Padding="0,40,0,0">

        <local:MyView/>

    </StackLayout>

 

但這裡希望可以在引用的時候變成他的提示文字,以及註冊按鈕的事件等,所以我們將ContentView所用的.cs檔開啟,加入一個提示屬性及一個事件。

 

        public string PlaceHolder

        {

            get { return this.entry.Placeholder; }

            set { this.entry.Placeholder = value; }

        }

 

        public event EventHandler OnButtonClick;

 

在建構子的地方註冊原本的Button Click事件,觸發控制項本身新建立的OnButtonClick

public MyView ()

{

  InitializeComponent ();

this.btn.Clicked += (sender, e) => this.OnButtonClick?.DynamicInvoke(sender, e);

}

 

Page頁面上引用該控制項的地方,就可使用前述自訂新增的屬性與事件

    <StackLayout Padding="0,40,0,0">

        <local:MyView  PlaceHolder="test"   OnButtonClick="MyButtonClick"   />

    </StackLayout>

 

3.3自訂控制項Binding

前述步驟我們建立的自訂的屬性與事件,但無法直接拿來做Binding的動作,因為它並非BindableProperty,若要更改成可被Binding的話需要再建立一個對應的BindableProperty

在自訂的ContentViewcs檔內,我們建立一個PlaceHolder用的BindableProperty命名為PlaceHolderProperty,如下:

        public static readonly BindableProperty PlaceHolderProperty =

            BindableProperty.Create(

                propertyName:"PlaceHolder",

                returnType: typeof(string),

                declaringType: typeof(MyView),

                defaultValue: null,

               defaultBindingMode: BindingMode.TwoWay);

這裡我們使用BindableProperty提供的靜態方法Create來建立BindableProperty,這裡使用的參數說明如下:

propertyName:要被Binding的屬性名稱
returnType:
Binding的屬性型別
declaringType:
Binding的屬性所在的類別型別
defaultValue:
Binding的屬性的預設值
defaultBindingMode:
Binding的方向類型

接著修改原本PlaceHoleder屬性內的GetSet,如下:

        public string PlaceHolder

        {

            get { return (string)this.GetValue(PlaceHolderProperty); }

            set { SetValue(PlaceHolderProperty, value); }

        }

依照相同的方式,我們建立Text,以及Command屬性與其BindableProperty,分別對應到EntryText屬性與ButtonCommand,這樣我們就完成了Page端使用時,與自訂控制項的Binding,但我們也必須讓自訂控制項內的ButtonEntry要使用的屬性Binding到相同的屬性上。如下XAML片段

   

    <StackLayout x:Name="stkLayout" Orientation="Horizontal" >

        <Entry

            Placeholder="{Binding PlaceHolder}"

            Text="{Binding Text}"

            HorizontalOptions="FillAndExpand"/>

        <Button Command="{Binding Command}" Text="Test" />

    </StackLayout>

 

控制項本身的BindingContext已經由Page決定了,所以在控制項內我們需要將其控制項Binding到自身的ContentView上,所以我們要將StackLayoutBindingContext做修改,如下程式碼片段

public MyView ()

{

  InitializeComponent ();

this.stkLayout.BindingContext = this;

}

 

最後建立一個ViewModel來測試Binding是否成功,XAML片段如下

 

    <StackLayout Padding="0,40,0,0">

        <local:MyView

            PlaceHolder="{Binding PlaceHolder}"  

            OnButtonClick="{Binding OnClick}"   />

    </StackLayout>

 

4.範例連結與參考來源

張阿鬼