XAML 中的原生檢視

Download Sample 下載範例

iOS、Android 和 通用 Windows 平台 的原生檢視可以直接從 Xamarin.Forms XAML 檔案參考。 屬性和事件處理程式可以在原生檢視上設定,而且可以與 Xamarin.Forms 檢視互動。 本文示範如何從 Xamarin.Forms XAML 檔案取用原生檢視。

若要將原生檢視內嵌至 Xamarin.Forms XAML 檔案:

  1. xmlns針對包含原生檢視的命名空間,在 XAML 檔案中新增命名空間宣告。
  2. 在 XAML 檔案中建立原生檢視的實例。

重要

針對任何使用原生檢視的 XAML 頁面,都必須停用已編譯的 XAML。 這可藉由使用 [XamlCompilation(XamlCompilationOptions.Skip)] 屬性裝飾 XAML 頁面的程式代碼後置類別來完成。 如需 XAML 編譯的詳細資訊,請參閱 中的 Xamarin.FormsXAML 編譯。

若要從程式代碼後置檔案參考原生檢視,您必須使用共用資產專案 (SAP),並使用條件式編譯指示詞包裝平臺特定程序代碼。 如需詳細資訊,請參閱 從程式代碼參考原生檢視。

取用原生檢視

下列程式代碼範例示範將每個平臺的原生檢視取用至 Xamarin.FormsContentPage

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
        xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
        xmlns:win="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
            Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        x:Class="NativeViews.NativeViewDemo">
    <StackLayout Margin="20">
        <ios:UILabel Text="Hello World" TextColor="{x:Static ios:UIColor.Red}" View.HorizontalOptions="Start" />
        <androidWidget:TextView Text="Hello World" x:Arguments="{x:Static androidLocal:MainActivity.Instance}" />
        <win:TextBlock Text="Hello World" />
    </StackLayout>
</ContentPage>

以及指定 原生檢視命名空間的 clr-namespaceassemblytargetPlatform 也必須指定 。 這應該設定為iOSAndroid、、 UWPWindows 、(相當於UWP)、macOSGTKTizen、 或 WPF。 在運行時間,XAML 剖析器會忽略任何與 targetPlatform 應用程式執行平臺不相符的 XML 命名空間前置詞。

每個命名空間宣告都可用來從指定的命名空間參考任何類別或結構。 例如, ios 命名空間宣告可用來參考 iOS UIKit 命名空間中的任何類別或結構。 原生檢視的屬性可以透過 XAML 設定,但屬性和物件類型必須相符。 例如,UILabel.TextColor屬性是使用x:Static標記延伸和ios命名空間設定為 UIColor.Red

您也可以使用 Class.BindableProperty="value" 語法,在原生檢視上設定可系結屬性和附加的可系結屬性。 每個原生檢視都會包裝在平臺特定 NativeViewWrapper 實例中,其衍生自 Xamarin.Forms.View 類別。 在原生檢視上設定可系結屬性或附加的可系結屬性會將屬性值傳送至包裝函式。 例如,您可以在原生檢視上設定 View.HorizontalOptions="Center" 置中水準版面配置。

注意

請注意,樣式不能與原生檢視搭配使用,因為樣式只能以物件支援 BindableProperty 的屬性為目標。

Android Widget 建構函式通常需要 Android Context 物件做為自變數,而且這可以透過 類別中的 MainActivity 靜態屬性來提供。 因此,在 XAML 中建立 Android 小工具時,Context物件通常必須使用具有x:Static標記延伸的屬性傳遞至 Widget 的建構x:Arguments函式。 如需詳細資訊,請參閱 將自變數傳遞至原生檢視

注意

請注意,在 .NET Standard 連結庫專案或共用資產專案 (SAP) 中,無法使用 命名原生檢視 x:Name 。 這樣做會產生原生類型的變數,這會導致編譯錯誤。 不過,原生檢視可以包裝在實例中 ContentView ,並在程式代碼後置檔案中擷取,前提是正在使用 SAP。 如需詳細資訊,請參閱 從程式代碼參考原生檢視。

原生系結

數據系結可用來同步處理UI與其數據源,並簡化應用程式如何 Xamarin.Forms 顯示及與其資料互動。 只要來源物件實作 INotifyPropertyChanged 介面,來源物件中的變更就會由系結架構自動推送至目標物件,而目標物件中的變更可以選擇性地推送至來源物件。

原生檢視的屬性也可以使用數據系結。 下列程式代碼範例示範使用原生檢視的屬性進行數據系結:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
        xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
        xmlns:win="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
            Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:local="clr-namespace:NativeSwitch"
        x:Class="NativeSwitch.NativeSwitchPage">
    <StackLayout Margin="20">
        <Label Text="Native Views Demo" FontAttributes="Bold" HorizontalOptions="Center" />
        <Entry Placeholder="This Entry is bound to the native switch" IsEnabled="{Binding IsSwitchOn}" />
        <ios:UISwitch On="{Binding Path=IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=ValueChanged}"
            OnTintColor="{x:Static ios:UIColor.Red}"
            ThumbTintColor="{x:Static ios:UIColor.Blue}" />
        <androidWidget:Switch x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
            Checked="{Binding Path=IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=CheckedChange}"
            Text="Enable Entry?" />
        <win:ToggleSwitch Header="Enable Entry?"
            OffContent="No"
            OnContent="Yes"
            IsOn="{Binding IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=Toggled}" />
    </StackLayout>
</ContentPage>

頁面包含 Entry 屬性 IsEnabled 系結至 屬性的 NativeSwitchPageViewModel.IsSwitchOnBindingContext頁面的 設定為程式代碼後置檔案中 類別的新實例NativeSwitchPageViewModel,而 ViewModel 類別會實作 INotifyPropertyChanged 介面。

此頁面也包含每個平臺的原生參數。 每個原生參數都會使用系 TwoWay 結來更新 屬性的值 NativeSwitchPageViewModel.IsSwitchOn 。 因此,當切換關閉時, Entry 會停用 ,而當切換開啟時, Entry 會啟用 。 下列螢幕快照顯示每個平臺上的這項功能:

Native Switch DisabledNative Switch Enabled

只要原生屬性在 iOS 上實 INotifyPropertyChanged作 、或支援 iOS 上的 Key-Value Observing (KVO),或是在 DependencyProperty UWP 上,則會自動支援雙向系結。 不過,許多原生檢視不支援屬性變更通知。 針對這些檢視,您可以將屬性值指定為系結表達式的一 UpdateSourceEventName 部分。 這個屬性應該設定為原生檢視中的事件名稱,以在目標屬性變更時發出訊號。 然後,當原生參數的值變更時, Binding 類別會通知用戶已變更參數值,並 NativeSwitchPageViewModel.IsSwitchOn 更新屬性值。

將自變數傳遞至原生檢視

建構函式自變數可以使用具有標記延伸的屬性x:Static傳遞至原生檢視x:Arguments。 此外,原生檢視處理站方法(public static 傳回與定義方法之類別或結構相同類型的物件或值的方法,可以使用 屬性指定方法的名稱 x:FactoryMethod ,並使用 屬性呼叫其自變數 x:Arguments

下列程式代碼範例示範這兩種技術:

<ContentPage ...
        xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
        xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidGraphics="clr-namespace:Android.Graphics;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
        xmlns:winControls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:winMedia="clr-namespace:Windows.UI.Xaml.Media;assembly=Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:winText="clr-namespace:Windows.UI.Text;assembly=Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:winui="clr-namespace:Windows.UI;assembly=Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows">
        ...
        <ios:UILabel Text="Simple Native Color Picker" View.HorizontalOptions="Center">
            <ios:UILabel.Font>
                <ios:UIFont x:FactoryMethod="FromName">
                    <x:Arguments>
                        <x:String>Papyrus</x:String>
                        <x:Single>24</x:Single>
                    </x:Arguments>
                </ios:UIFont>
            </ios:UILabel.Font>
        </ios:UILabel>
        <androidWidget:TextView x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
                    Text="Simple Native Color Picker"
                    TextSize="24"
                    View.HorizontalOptions="Center">
            <androidWidget:TextView.Typeface>
                <androidGraphics:Typeface x:FactoryMethod="Create">
                    <x:Arguments>
                        <x:String>cursive</x:String>
                        <androidGraphics:TypefaceStyle>Normal</androidGraphics:TypefaceStyle>
                    </x:Arguments>
                </androidGraphics:Typeface>
            </androidWidget:TextView.Typeface>
        </androidWidget:TextView>
        <winControls:TextBlock Text="Simple Native Color Picker"
                    FontSize="20"
                    FontStyle="{x:Static winText:FontStyle.Italic}"
                    View.HorizontalOptions="Center">
            <winControls:TextBlock.FontFamily>
                <winMedia:FontFamily>
                    <x:Arguments>
                        <x:String>Georgia</x:String>
                    </x:Arguments>
                </winMedia:FontFamily>
            </winControls:TextBlock.FontFamily>
        </winControls:TextBlock>
        ...
</ContentPage>

UIFont.FromName Factory 方法可用來在 iOS 上將 UILabel.Font 屬性設定為新的 UIFont 。 名稱和 UIFont 大小是由屬性子 x:Arguments 系的方法自變數所指定。

Typeface.Create Factory 方法可用來在 Android 上將 屬性設定TextView.Typeface為新的 TypefaceTypeface系列名稱和樣式是由屬性子x:Arguments系的方法自變數所指定。

FontFamily構函式可用來將 屬性設定TextBlock.FontFamily為 通用 Windows 平台 (UWP) 上的新FontFamily屬性。 名稱 FontFamily 是由屬性的 x:Arguments 子系方法自變數所指定。

注意

自變數必須符合建構函式或 Factory 方法所需的類型。

下列螢幕快照顯示指定 Factory 方法和建構函式自變數的結果,以在不同的原生檢視上設定字型:

Setting Fonts on Native Views

如需在 XAML 中傳遞自變數的詳細資訊,請參閱 在 XAML 中傳遞自變數。

從程式代碼參考原生檢視

雖然無法使用 屬性來命名原生檢視x:Name,但可以從共用存取專案中的程序代碼後置檔案擷取 XAML 檔案中宣告的原生檢視實例,前提是原生檢視是指定x:Name屬性值的ContentView子系。 然後,在程式代碼後置檔案的條件式編譯指示詞內,您應該:

  1. 擷取 ContentView.Content 屬性值,並將其轉換成平臺特定 NativeViewWrapper 類型。
  2. 擷取 屬性, NativeViewWrapper.NativeElement 並將其轉換成原生檢視類型。

接著可以在原生檢視上叫用原生 API,以執行所需的作業。 此方法也提供不同平臺的多個 XAML 原生檢視可以是相同 ContentView子系的優點。 下列程式代碼範例示範這項技術:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
        xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
        xmlns:winControls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
            Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:local="clr-namespace:NativeViewInsideContentView"
        x:Class="NativeViewInsideContentView.NativeViewInsideContentViewPage">
    <StackLayout Margin="20">
        <ContentView x:Name="contentViewTextParent" HorizontalOptions="Center" VerticalOptions="CenterAndExpand">
            <ios:UILabel Text="Text in a UILabel" TextColor="{x:Static ios:UIColor.Red}" />
            <androidWidget:TextView x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
                Text="Text in a TextView" />
              <winControls:TextBlock Text="Text in a TextBlock" />
        </ContentView>
        <ContentView x:Name="contentViewButtonParent" HorizontalOptions="Center" VerticalOptions="EndAndExpand">
            <ios:UIButton TouchUpInside="OnButtonTap" View.HorizontalOptions="Center" View.VerticalOptions="Center" />
            <androidWidget:Button x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
                Text="Scale and Rotate Text"
                Click="OnButtonTap" />
            <winControls:Button Content="Scale and Rotate Text" />
        </ContentView>
    </StackLayout>
</ContentPage>

在上述範例中,每個平臺的原生檢視都是控件的 ContentView 子系,而 x:Name 屬性值會用來擷取 ContentView 程式代碼後置中的 :

public partial class NativeViewInsideContentViewPage : ContentPage
{
    public NativeViewInsideContentViewPage()
    {
        InitializeComponent();

#if __IOS__
        var wrapper = (Xamarin.Forms.Platform.iOS.NativeViewWrapper)contentViewButtonParent.Content;
        var button = (UIKit.UIButton)wrapper.NativeView;
        button.SetTitle("Scale and Rotate Text", UIKit.UIControlState.Normal);
        button.SetTitleColor(UIKit.UIColor.Black, UIKit.UIControlState.Normal);
#endif
#if __ANDROID__
        var wrapper = (Xamarin.Forms.Platform.Android.NativeViewWrapper)contentViewTextParent.Content;
        var textView = (Android.Widget.TextView)wrapper.NativeView;
        textView.SetTextColor(Android.Graphics.Color.Red);
#endif
#if WINDOWS_UWP
        var textWrapper = (Xamarin.Forms.Platform.UWP.NativeViewWrapper)contentViewTextParent.Content;
        var textBlock = (Windows.UI.Xaml.Controls.TextBlock)textWrapper.NativeElement;
        textBlock.Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.Red);
        var buttonWrapper = (Xamarin.Forms.Platform.UWP.NativeViewWrapper)contentViewButtonParent.Content;
        var button = (Windows.UI.Xaml.Controls.Button)buttonWrapper.NativeElement;
        button.Click += (sender, args) => OnButtonTap(sender, EventArgs.Empty);
#endif
    }

    async void OnButtonTap(object sender, EventArgs e)
    {
        contentViewButtonParent.Content.IsEnabled = false;
        contentViewTextParent.Content.ScaleTo(2, 2000);
        await contentViewTextParent.Content.RotateTo(360, 2000);
        contentViewTextParent.Content.ScaleTo(1, 2000);
        await contentViewTextParent.Content.RelRotateTo(360, 2000);
        contentViewButtonParent.Content.IsEnabled = true;
    }
}

屬性 ContentView.Content 是用來擷取包裝的原生檢視做為平臺特定 NativeViewWrapper 實例。 NativeViewWrapper.NativeElement接著會存取 屬性,以擷取原生檢視做為其原生類型。 接著會叫用原生檢視的 API 來執行所需的作業。

iOS 和 Android 原生按鈕會共用相同的 OnButtonTap 事件處理程式,因為每個原生按鈕都會 EventHandler 取用委派來回應觸控事件。 不過,通用 Windows 平台 (UWP) 會使用個別RoutedEventHandler的,進而OnButtonTap取用此範例中的事件處理程式。 因此,按兩下原生按鈕時,OnButtonTap事件處理程式會執行,這會調整並旋轉具名contentViewTextParent內所含的ContentView原生控件。 下列螢幕快照示範這在每個平台上發生:

ContentView Containing a Native Control

子類別原生檢視

許多 iOS 和 Android 原生檢視不適合在 XAML 中具現化,因為它們會使用方法來設定控件,而不是屬性。 此問題的解決方案是,包裝函式中的子類別原生檢視會定義更易用 XAML 的 API,以使用屬性來設定控件,以及使用平台無關的事件。 然後,包裝的原生檢視可以放在共用資產專案 (SAP) 中,並以條件式編譯指示詞括住,或放在平臺特定專案中,並在 .NET Standard 連結庫專案中從 XAML 參考。

下列程式代碼範例示範使用 Xamarin.Forms 子類別化原生檢視的頁面:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
        xmlns:iosLocal="clr-namespace:SubclassedNativeControls.iOS;assembly=SubclassedNativeControls.iOS;targetPlatform=iOS"
        xmlns:android="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
        xmlns:androidLocal="clr-namespace:SubclassedNativeControls.Droid;assembly=SubclassedNativeControls.Droid;targetPlatform=Android"
        xmlns:winControls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
            Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
        xmlns:local="clr-namespace:SubclassedNativeControls"
        x:Class="SubclassedNativeControls.SubclassedNativeControlsPage">
    <StackLayout Margin="20">
        <Label Text="Subclassed Native Views Demo" FontAttributes="Bold" HorizontalOptions="Center" />
        <StackLayout Orientation="Horizontal">
          <Label Text="You have chosen:" />
          <Label Text="{Binding SelectedFruit}" />      
        </StackLayout>
        <iosLocal:MyUIPickerView ItemsSource="{Binding Fruits}"
            SelectedItem="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=SelectedItemChanged}" />
        <androidLocal:MySpinner x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
            ItemsSource="{Binding Fruits}"
            SelectedObject="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=ItemSelected}" />
        <winControls:ComboBox ItemsSource="{Binding Fruits}"
            SelectedItem="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=SelectionChanged}" />
    </StackLayout>
</ContentPage>

頁面包含 , Label 顯示使用者從原生控件選擇的水果。 系 Label 結至 SubclassedNativeControlsPageViewModel.SelectedFruit 屬性。 BindingContext頁面的 設定為程式代碼後置檔案中 類別的新實例SubclassedNativeControlsPageViewModel,而 ViewModel 類別會實作 INotifyPropertyChanged 介面。

此頁面也包含每個平臺的原生選擇器檢視。 每個原生檢視都會藉由將 ItemSource 水果的 屬性系結至 SubclassedNativeControlsPageViewModel.Fruits 集合來顯示結果集合。 這可讓用戶挑選水果,如下列螢幕快照所示:

Subclassed Native Views

在iOS和Android上,原生選擇器會使用方法來設定控件。 因此,這些選擇器必須進行子類別化,才能公開屬性,使其具有 XAML 的友好性。 在 通用 Windows 平台 (UWP) 上,ComboBox已經是 XAML 易記,因此不需要子類別。

iOS

iOS 實作會子 UIPickerView 類別檢視,並公開屬性和可從 XAML 輕鬆取用的事件:

public class MyUIPickerView : UIPickerView
{
    public event EventHandler<EventArgs> SelectedItemChanged;

    public MyUIPickerView()
    {
        var model = new PickerModel();
        model.ItemChanged += (sender, e) =>
        {
            if (SelectedItemChanged != null)
            {
                SelectedItemChanged.Invoke(this, e);
            }
        };
        Model = model;
    }

    public IList<string> ItemsSource
    {
        get
        {
            var pickerModel = Model as PickerModel;
            return (pickerModel != null) ? pickerModel.Items : null;
        }
        set
        {
            var model = Model as PickerModel;
            if (model != null)
            {
                model.Items = value;
            }
        }
    }

    public string SelectedItem
    {
        get { return (Model as PickerModel).SelectedItem; }
        set { }
    }
}

類別 MyUIPickerViewItemsSource 公開 和 SelectedItem 屬性,以及 SelectedItemChanged 事件。 UIPickerView需要屬性和事件存取MyUIPickerView的基礎UIPickerViewModel數據模型。 資料 UIPickerViewModel 模型是由 PickerModel 類別提供:

class PickerModel : UIPickerViewModel
{
    int selectedIndex = 0;
    public event EventHandler<EventArgs> ItemChanged;
    public IList<string> Items { get; set; }

    public string SelectedItem
    {
        get
        {
            return Items != null && selectedIndex >= 0 && selectedIndex < Items.Count ? Items[selectedIndex] : null;
        }
    }

    public override nint GetRowsInComponent(UIPickerView pickerView, nint component)
    {
        return Items != null ? Items.Count : 0;
    }

    public override string GetTitle(UIPickerView pickerView, nint row, nint component)
    {
        return Items != null && Items.Count > row ? Items[(int)row] : null;
    }

    public override nint GetComponentCount(UIPickerView pickerView)
    {
        return 1;
    }

    public override void Selected(UIPickerView pickerView, nint row, nint component)
    {
        selectedIndex = (int)row;
        if (ItemChanged != null)
        {
            ItemChanged.Invoke(this, new EventArgs());
        }
    }
}

類別PickerModel會透過 Items 屬性提供 MyUIPickerView 類別的基礎記憶體。 每當變更中 MyUIPickerView 選取的專案時, Selected 就會執行 方法,以更新選取的索引並引發 ItemChanged 事件。 這可確保 SelectedItem 屬性一律會傳回使用者挑選的最後一個專案。 此外,類別 PickerModel 會覆寫用來設定 MyUIPickerView 實例的方法。

Android

Android 實作會子 Spinner 類別檢視,並公開可從 XAML 輕鬆取用的屬性和事件:

class MySpinner : Spinner
{
    ArrayAdapter adapter;
    IList<string> items;

    public IList<string> ItemsSource
    {
        get { return items; }
        set
        {
            if (items != value)
            {
                items = value;
                adapter.Clear();

                foreach (string str in items)
                {
                    adapter.Add(str);
                }
            }
        }
    }

    public string SelectedObject
    {
        get { return (string)GetItemAtPosition(SelectedItemPosition); }
        set
        {
            if (items != null)
            {
                int index = items.IndexOf(value);
                if (index != -1)
                {
                    SetSelection(index);
                }
            }
        }
    }

    public MySpinner(Context context) : base(context)
    {
        ItemSelected += OnBindableSpinnerItemSelected;

        adapter = new ArrayAdapter(context, Android.Resource.Layout.SimpleSpinnerItem);
        adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
        Adapter = adapter;
    }

    void OnBindableSpinnerItemSelected(object sender, ItemSelectedEventArgs args)
    {
        SelectedObject = (string)GetItemAtPosition(args.Position);
    }
}

類別 MySpinnerItemsSource 公開 和 SelectedObject 屬性,以及 ItemSelected 事件。 類別所MySpinner顯示的專案是由Adapter與檢視相關聯的 提供,而專案會在屬性第一次設定時ItemsSource填入 。Adapter 每當類別中 MySpinner 選取的項目變更時,事件處理程式就會 OnBindableSpinnerItemSelected 更新 SelectedObject 屬性。