采用 XAML 的本机视图
iOS、Android 和通用 Windows 平台的本机视图可直接从 Xamarin.Forms XAML 文件引用。 可以在本机视图上设置属性和事件处理程序,并且可以与 Xamarin.Forms 视图交互。 本文演示如何从 Xamarin.Forms XAML 文件使用本机视图。
若要将本机视图嵌入到 Xamarin.Forms XAML 文件中,请执行以下操作:
- 在 XAML 文件中为包含本机视图的命名空间添加
xmlns
命名空间声明。 - 在 XAML 文件中创建本机视图的实例。
重要
对于使用本机视图的任何 XAML 页面,必须禁用已编译的 XAML。 这可以通过使用 [XamlCompilation(XamlCompilationOptions.Skip)]
特性修饰 XAML 页面的代码隐藏类来实现。 有关 XAML 编译的详细信息,请参阅 Xamarin.Forms 中的 XAML 编译。
若要从代码隐藏文件中引用本机视图,必须使用共享资产项目 (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-namespace
和 assembly
外,还必须指定targetPlatform
。 这应该设置为 iOS
、Android
、UWP
、Windows
(相当于 UWP
)、macOS
、GTK
、Tizen
或 WPF
。 在运行时,XAML 分析程序将忽略具有与运行应用程序的平台不匹配的 targetPlatform
的任何 XML 命名空间前缀。
每个命名空间声明都可用于引用指定命名空间中的任何类或结构。 例如,ios
命名空间声明可用于引用 iOS UIKit
命名空间中的任何类或结构。 可以通过 XAML 设置本机视图的属性,但属性和对象类型必须匹配。 例如,使用 x:Static
标记扩展和 ios
命名空间将 UILabel.TextColor
属性设置为 UIColor.Red
。
也可以使用 Class.BindableProperty="value"
语法在本机视图中设置可绑定属性和附加的可绑定属性。 每个本机视图都包装在特定于平台的 NativeViewWrapper
实例中,该实例派生自 Xamarin.Forms.View
类。 在本机视图中设置可绑定属性或附加的可绑定属性会将属性值传输到包装器。 例如,可以通过在本机视图中设置 View.HorizontalOptions="Center"
来指定居中水平布局。
注意
请注意,样式不能与本机视图一起使用,因为样式只能以 BindableProperty
对象支持的属性为目标。
Android 小组件构造函数通常需要 Android Context
对象作为自变量,这可以通过 MainActivity
类中的静态属性来实现。 因此,在 XAML 中创建 Android 小组件时,通常必须使用具有 x:Static
标记扩展的 x:Arguments
特性将 Context
对象传递给小组件的构造函数。 有关详细信息,请参阅将自变量传递给本机视图。
注意
请注意,在 .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.IsSwitchOn
属性。 页面的 BindingContext
设置为代码隐藏文件中 NativeSwitchPageViewModel
类的新实例,ViewModel 类实现 INotifyPropertyChanged
接口。
该页还包含每个平台的本机开关。 每个本机开关都使用 TwoWay
绑定来更新 NativeSwitchPageViewModel.IsSwitchOn
属性的值。 因此,当开关关闭时,Entry
被禁用,当开关打开时,Entry
启用。 以下屏幕截图显示了每个平台上的此功能:
如果本机属性实现 INotifyPropertyChanged
,或在 iOS 上支持键值观测 (KVO),或在 UWP 上是 DependencyProperty
,则自动支持双向绑定。 但是,许多本机视图不支持属性更改通知。 对于这些视图,可以将 UpdateSourceEventName
属性值指定为绑定表达式的一部分。 此属性应设置为本机视图中事件的名称,该名称指示目标属性发生更改时发出信号。 然后,当本机开关的值发生更改时,系统会通知 Binding
类用户已更改开关值,并且 NativeSwitchPageViewModel.IsSwitchOn
属性值也将更新。
将自变量传递给本机视图
可以使用具有 x:Static
标记扩展的 x:Arguments
特性将构造函数自变量传递给本机视图。 此外,可以通过使用 x:FactoryMethod
特性指定方法的名称,并使用 x:Arguments
特性指定其自变量来调用本机视图工厂方法(public static
方法,返回与定义方法的类或结构相同类型的对象或值)。
下面的代码示例演示了这两种技术:
<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
工厂方法用于在 iOS 上将 UILabel.Font
属性设置为新的 UIFont
。 UIFont
名称和大小是由属于 x:Arguments
特性子级的方法自变量指定的。
Typeface.Create
工厂方法用于在 Android 上将 TextView.Typeface
属性设置为新的 Typeface
。 Typeface
系列名称和样式是由属于 x:Arguments
特性子级的方法自变量指定的。
FontFamily
构造函数用于在通用 Windows 平台 (UWP) 上将 TextBlock.FontFamily
属性设置为新的 FontFamily
。 FontFamily
名称是由属于 x:Arguments
特性子级的方法自变量指定的。
注意
自变量必须与构造函数或工厂方法所需的类型匹配。
以下屏幕截图显示了指定工厂方法和构造函数自变量以在不同本机视图上设置字体的结果:
有关在 XAML 中传递自变量的详细信息,请参阅在 XAML 中传递自变量。
从代码引用本机视图
虽然无法使用 x:Name
特性命名本机视图,但可以从共享访问项目中的代码隐藏文件中检索 XAML 文件中声明的本机视图实例,前提是该本机视图是指定 x:Name
特性值的 ContentView
的子级。 然后,在代码隐藏文件中的条件编译指令内,应:
- 检索
ContentView.Content
属性值,并将其强制转换为特定于平台的NativeViewWrapper
类型。 - 检索
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
事件处理程序,该处理程序将缩放和旋转 ContentView
中包含的名为 contentViewTextParent
的本机控件。 以下屏幕截图演示了每个平台上发生的情况:
子类本机视图
许多 iOS 和 Android 本机视图不适合在 XAML 中实例化,因为它们使用方法而不是属性来设置控件。 此问题的解决方案是在包装器中对本机视图进行子类化,该包装器定义了一个更适合 XAML 的 API,该 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
集合来显示水果集合。 这允许用户选取水果,如以下屏幕截图所示:
在 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 { }
}
}
MyUIPickerView
类公开 ItemsSource
和 SelectedItem
属性以及 SelectedItemChanged
事件。 UIPickerView
需要基础 UIPickerViewModel
数据模型,该模型由 MyUIPickerView
属性和事件访问。 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);
}
}
MySpinner
类公开 ItemsSource
和 SelectedObject
属性以及 ItemSelected
事件。 MySpinner
类显示的项由与视图关联的 Adapter
提供,当首次设置 ItemsSource
属性时,项将填充到 Adapter
中。 每当 MySpinner
类中的选定项发生更改时,OnBindableSpinnerItemSelected
事件处理程序将更新 SelectedObject
属性。