简体   繁体   English

Xamarin.Android和Spinner与ReactiveUI绑定

[英]Xamarin.Android and Spinner binding with ReactiveUI

I'm trying to bind to a Spinner using ReactiveUI in a Xamarin.Android application. 我正在尝试在Xamarin.Android应用程序中使用ReactiveUI绑定到Spinner。 To add items to the Spinner , I need to use ArrayAdapter . 要将项目添加到Spinner ,我需要使用ArrayAdapter But ArrayAdapter needs Android.Content.Context . 但是ArrayAdapter需要Android.Content.Context Should I pass it into the ViewModel? 我应该将其传递给ViewModel吗?

Anyone know about an application written in Xamarin.Android, which uses ReactiveUI, where I could look inspiration? 任何人都知道用Xamarin.Android编写的使用ReactiveUI的应用程序,在哪里可以找到灵感? The ReactiveUI documentation only has a reference to a sample application written for iOS. ReactiveUI文档仅引用了为iOS编写的示例应用程序。

View 视图

    <?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; } }
    }
}

ViewModel 视图模型

namespace Test.Droid.ViewModels
{
    public class MainViewModel : ReactiveObject
    {
        // How to databind Spinner Devices ?


        public MainViewModel()
        {           
        }
    }
}

I haven't done any Xamarin.Android development, but in general you don't want to pass details about the view into the ViewModel - it should not know anything about the view. 我还没有做过Xamarin.Android开发,但是总的来说,您不想将有关视图的详细信息传递给ViewModel-它不应该对视图有任何了解。

I would expose the list of items as a collection (eg IList<Item> ) and use a converter on the binding to create an ArrayAdapter : 我将项目列表作为集合公开(例如IList<Item> ),并在绑定上使用转换器创建ArrayAdapter

this.OneWayBind(this.ViewModel.Devices, this.View.Property, devices => new ArrayAdapter(devices));

this.View.Property should refer to the property that changes whenever the list of devices changes. this.View.Property应该引用每当设备列表更改时更改的属性。 The third parameter ( devices => new ArrayAdapter() ) receives the property from the ViewModel as an argument, you then return a value that can be set on the this.View.Property . 第三个参数( devices => new ArrayAdapter() )从ViewModel接收属性作为参数,然后返回可以在this.View.Property上设置的this.View.Property

For example: 例如:

  • ViewModel.Count is a string ViewModel.Count是一个string
  • View.Property is an int View.Property是一个int

Bind like this: 像这样绑定:

 this.OneWayBind(this.ViewModel.Count, this.View.Property, count => int.Parse(count)); 

The third parameter can be a function or lambda that accepts an argument of the type of the ViewModel property and returns a value of the type of the view property. 第三个参数可以是接受ViewModel属性类型的参数并返回view属性类型的值的函数或lambda。

I'd said I'd given in providing any feedback on Stackoverflow but anyway... we have a collection of binding extensions, one of which is for a Spinner. 我说过我会提供有关Stackoverflow的任何反馈,但是无论如何...我们有一系列绑定扩展,其中一个是Spinner。 in typical usage it looks like this 在典型用法中,它看起来像这样

        // 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));

where in this case, the extension method looks like 在这种情况下,扩展方法看起来像

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
        {

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM