MvvmCross / MvvmCross-AndroidSupport

Android support library packages for MvvmCross: The .NET MVVM framework for cross-platform solutions.
http://mvvmcross.com
15 stars 0 forks source link

MvxSpinner won't work inside fragment #234

Closed mufid closed 8 years ago

mufid commented 8 years ago

I got error when attaching MvxSpinner inside a MvxFragment. However, it works fine inside an MvxActivity

Steps to reproduce

2016-05-09_12-56-16

From the attached example repo:

  1. Login to "XPlatformMenu", run the Android version
  2. Go to ViewPager from Menu, move to Spinner tab
  3. Change the value of the spinner
  4. The property does not match the selected spinner

Also, i get this error message:

05-09 13:03:31.125 2360 2360 I MvxBind : 21.60 Failed to create target binding for binding SelectedItem for FruitSelected

Example code of the issue available below.

Expected behavior

The SelectedItem should be changed

Actual behavior

It does nothing

Configuration

Version: 4.0.0 (I also test in latest 4.1 version, but the results are the same). Platform: Android

Code

Only important details attached here. Complete git repository exists here: https://github.com/mufid/MvxSpinner-Bug

fragment_spinner.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <MvxSpinner
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        local:MvxBind="ItemsSource Fruits;SelectedItem FruitSelected" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:text="This will be the text"
        local:MvxBind="Text SelectedText" />
</LinearLayout>

SpinnerViewModel.cs


    public class Fruit
    {
        public Fruit(string Name)
        {
            this.Name = Name;
        }

        public string Name { get; private set; }

        public override int GetHashCode()
        {
            return Name?.GetHashCode() ?? -1;
        }

        public override bool Equals(object obj)
        {
            return Name == (obj as Fruit)?.Name;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    public class SpinnerViewModel : BaseViewModel
    {
        private List<Fruit> _fruits = new List<Fruit>()
        {
            new Fruit("Mango"),
            new Fruit("Orange")
        };
        public List<Fruit> Fruits
        {
            get { return _fruits; }
            set { _fruits = value; RaisePropertyChanged(() => Fruits); }
        }

        public Fruit _fruitSelected = new Fruit("Orange");
        public Fruit FruitSelected
        {
            get { return _fruitSelected; }
            set
            {
                _fruitSelected = value;
                RaisePropertyChanged(() => SelectedText);
                RaisePropertyChanged(() => FruitSelected);
            }
        }

        public string SelectedText
        {
            get { return $"You select {FruitSelected}"; }
        }
    }
Cheesebaron commented 8 years ago

Can you try adding this to the Setup.cs file on Droid:

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
    MvxAppCompatSetupHelper.FillTargetFactories(registry);
    base.FillTargetFactories(registry);
}
mufid commented 8 years ago

Is there something missing / i should add? It says that "no suitable method to override"

Edit: i should use MvvmCross.Binding.Bindings.Target.Construction; namespace. I didn't know why Intellisense does not automatically use that for me. Now working on it.

mufid commented 8 years ago

Thanks! Now it is working perfectly. We can close this issue, but i wonder what FillTargetFactories does?

2016-05-09_22-06-58

Cheesebaron commented 8 years ago

Thing here is that the MvxSpinner in this case is actually a MvxAppCompatSpinner and not an MvxSpinner directly. The original binding targets are made for non-AppCompat widgets and view. A new set of binding targets were made for AppCompat specific views. However, they are not applied automatically. This is also missing from the example you are using, so adding that specific line registers those new view types to their respective bindings.