Xamarin.Android 和 Spinner 与 ReactiveUI 绑定
Xamarin.Android and Spinner binding with ReactiveUI
我正在尝试在 Xamarin.Android 应用程序中使用 ReactiveUI 绑定到 Spinner。要将项目添加到 Spinner
,我需要使用 ArrayAdapter
。但是 ArrayAdapter
需要 Android.Content.Context
。我应该将它传递给 ViewModel 吗?
有人知道用 Xamarin.Android 编写的应用程序,它使用 ReactiveUI,我可以在哪里寻找灵感? ReactiveUI 文档仅引用了为 iOS.
编写的示例应用程序
查看
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/Label"
android:text="Zařízení:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Spinner
android:id="@+id/Devices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/Label"/>
<Button
android:id="@+id/EditCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/Devices"
android:text="Edit"/>
</RelativeLayout>
Activity
namespace Test.Droid
{
[Activity(Label = "Test.Droid", MainLauncher = true)]
public class MainActivity : ReactiveActivity, IViewFor<MainViewModel>
{
public Spinner Devices { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
ViewModel = new MainViewModel();
this.WireUpControls();
// Bindings
this.Bind(this.ViewModel, ) // ?
}
private MainViewModel _viewModel;
public MainViewModel ViewModel
{ get => _viewModel; set { this.RaiseAndSetIfChanged(ref _viewModel, value); } }
object IViewFor.ViewModel
{ get => ViewModel; set { ViewModel = (MainViewModel)value; } }
}
}
视图模型
namespace Test.Droid.ViewModels
{
public class MainViewModel : ReactiveObject
{
// How to databind Spinner Devices ?
public MainViewModel()
{
}
}
}
我没有做过任何 Xamarin.Android 开发,但通常您不想将有关视图的详细信息传递到 ViewModel - 它不应该知道有关视图的任何信息。
我会将项目列表公开为一个集合(例如 IList<Item>
)并在绑定上使用转换器来创建 ArrayAdapter
:
this.OneWayBind(this.ViewModel.Devices, this.View.Property, devices => new ArrayAdapter(devices));
this.View.Property
应该是指随着设备列表的变化而变化的 属性。第三个参数 (devices => new ArrayAdapter()
) 从 ViewModel 接收 属性 作为参数,然后 return 一个可以在 this.View.Property
.
上设置的值
For example:
ViewModel.Count
is a string
View.Property
is an int
Bind like this:
this.OneWayBind(this.ViewModel.Count, this.View.Property, count => int.Parse(count));
第三个参数可以是接受 ViewModel 属性 类型参数和 return 视图类型值 属性 的函数或 lambda。
我说过我会提供有关 Whosebug 的任何反馈,但无论如何...我们有一组绑定扩展,其中之一是针对 Spinner 的。在典型用法中它看起来像这样
// bind the options for the distance
this.BindSpinner(ViewModel,
vm => vm.TravelLimitSelected,
vm => vm.CurrentTravelLimit,
vm => vm.TravelLimitChoices.Distances,
f => f.travelLimitSpinner,
(items) =>
new ActionSpinnerAdapter<DistanceChoiceModel>((c, p) => new DistanceLimitViewHost(c, p), items));
在这种情况下,扩展方法看起来像
public static IDisposable BindSpinner<TView, TViewModel, TCommandProp, TSpinnerViewModel>(
this TView view,
TViewModel viewModel,
Expression<Func<TViewModel, TCommandProp>> viewModelCommandName,
Expression<Func<TViewModel, int>> viewModelSelectedPropertyName,
Expression<Func<TViewModel, IList<TSpinnerViewModel>>> viewModelSourceItemsName,
Expression<Func<TView, Spinner>> spinnerControl, Func<IList<TSpinnerViewModel>, ISpinnerAdapter> adapterFactory) where TViewModel : RxViewModel
where TCommandProp : ICommand
where TView : class, IViewFor<TViewModel>
where TSpinnerViewModel : class
{
我正在尝试在 Xamarin.Android 应用程序中使用 ReactiveUI 绑定到 Spinner。要将项目添加到 Spinner
,我需要使用 ArrayAdapter
。但是 ArrayAdapter
需要 Android.Content.Context
。我应该将它传递给 ViewModel 吗?
有人知道用 Xamarin.Android 编写的应用程序,它使用 ReactiveUI,我可以在哪里寻找灵感? ReactiveUI 文档仅引用了为 iOS.
编写的示例应用程序查看
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/Label"
android:text="Zařízení:"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Spinner
android:id="@+id/Devices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/Label"/>
<Button
android:id="@+id/EditCommand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/Devices"
android:text="Edit"/>
</RelativeLayout>
Activity
namespace Test.Droid
{
[Activity(Label = "Test.Droid", MainLauncher = true)]
public class MainActivity : ReactiveActivity, IViewFor<MainViewModel>
{
public Spinner Devices { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
ViewModel = new MainViewModel();
this.WireUpControls();
// Bindings
this.Bind(this.ViewModel, ) // ?
}
private MainViewModel _viewModel;
public MainViewModel ViewModel
{ get => _viewModel; set { this.RaiseAndSetIfChanged(ref _viewModel, value); } }
object IViewFor.ViewModel
{ get => ViewModel; set { ViewModel = (MainViewModel)value; } }
}
}
视图模型
namespace Test.Droid.ViewModels
{
public class MainViewModel : ReactiveObject
{
// How to databind Spinner Devices ?
public MainViewModel()
{
}
}
}
我没有做过任何 Xamarin.Android 开发,但通常您不想将有关视图的详细信息传递到 ViewModel - 它不应该知道有关视图的任何信息。
我会将项目列表公开为一个集合(例如 IList<Item>
)并在绑定上使用转换器来创建 ArrayAdapter
:
this.OneWayBind(this.ViewModel.Devices, this.View.Property, devices => new ArrayAdapter(devices));
this.View.Property
应该是指随着设备列表的变化而变化的 属性。第三个参数 (devices => new ArrayAdapter()
) 从 ViewModel 接收 属性 作为参数,然后 return 一个可以在 this.View.Property
.
For example:
ViewModel.Count
is astring
View.Property
is anint
Bind like this:
this.OneWayBind(this.ViewModel.Count, this.View.Property, count => int.Parse(count));
第三个参数可以是接受 ViewModel 属性 类型参数和 return 视图类型值 属性 的函数或 lambda。
我说过我会提供有关 Whosebug 的任何反馈,但无论如何...我们有一组绑定扩展,其中之一是针对 Spinner 的。在典型用法中它看起来像这样
// bind the options for the distance
this.BindSpinner(ViewModel,
vm => vm.TravelLimitSelected,
vm => vm.CurrentTravelLimit,
vm => vm.TravelLimitChoices.Distances,
f => f.travelLimitSpinner,
(items) =>
new ActionSpinnerAdapter<DistanceChoiceModel>((c, p) => new DistanceLimitViewHost(c, p), items));
在这种情况下,扩展方法看起来像
public static IDisposable BindSpinner<TView, TViewModel, TCommandProp, TSpinnerViewModel>(
this TView view,
TViewModel viewModel,
Expression<Func<TViewModel, TCommandProp>> viewModelCommandName,
Expression<Func<TViewModel, int>> viewModelSelectedPropertyName,
Expression<Func<TViewModel, IList<TSpinnerViewModel>>> viewModelSourceItemsName,
Expression<Func<TView, Spinner>> spinnerControl, Func<IList<TSpinnerViewModel>, ISpinnerAdapter> adapterFactory) where TViewModel : RxViewModel
where TCommandProp : ICommand
where TView : class, IViewFor<TViewModel>
where TSpinnerViewModel : class
{