Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVMCross Bindings in Android

I'm developing a cross-platform App starting it in android. I've found your MVVMCross project and I'm trying to get into it. Right now I'm totally new to it and don't know how to bind my WebService-Results to my ListView. Here a bit of XAML as example how I'm trying it:

xmlns:mobsales="http://schemas.android.com/apk/res/MobSales.DroidUI"
... 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
android:layout_marginLeft="5dp" 
mobsales:MvxItemTemplate="@layout/listitem_customer" 
mobsales:MvxBind="{'ItemSource':{'Path':'Customer'}}" /> 
...

exactly looks like this

<cirrious.mvvmcross.binding.android.views.MvxBindableListView
        android:id="@+id/autocomplete"
        android:layout_below="@id/txtfield"
        android:layout_centerHorizontal="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        mobsales:MvxItemTemplate="@layout/listitem_customer"
        mobsales:MvxBind="{'ItemSource':{'Path':'Customers'}}" />

When I'm hovering the last two lines the tooltip says attribute is not declared. I really don't know how you do this. Can you give me some advice? I think I have to write some xml in the Values of my UI project, right?

Another question: How could I use AutoCompleteTextViews? Do I have to write my own MvXBindables first for it? Any advice? :-)

like image 350
Martin Avatar asked May 08 '12 08:05

Martin


1 Answers

To get these attributes to bind you need to include the namespace - which it looks like you've done.

You also need to include the MvxBindingAttributes.xml file into your UI project - https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/ResourcesToCopy/MvxBindingAttributes.xml - and you must set the build action of this file to "AndroidResource"

For an example, see any of the Android sample projects - https://github.com/slodge/MvvmCross


For the second part of your question about adding bindings, the binding framework should automatically one-way bind (from ViewModel to View) to existing public Properties on any Monodroid View/widget.

If the public Property isn't of the correct type (e.g. it's some Android enumeration instead of a View), then you can use an IMvxValueConverter to do the conversion.

If you want to do 2-way binding, or there isn't a public Property for what you want to bind to, then you fairly easily do a custom binding. For an example of this, see the custom IsFavorite 2 way binding in the conference sample

This code adds a new bindable pseudo-property "IsFavorite" to every Android Button.

... this is initialised in Setup.cs using code like:

    protected override void FillTargetFactories(MvvmCross.Binding.Interfaces.Bindings.Target.Construction.IMvxTargetBindingFactoryRegistry registry)
    {
        base.FillTargetFactories(registry);

        registry.RegisterFactory(
                    new MvxCustomBindingFactory<Button>(
                       "IsFavorite", 
                       (button) => new FavoritesButtonBinding(button)));
    }

... and the binding code is:

public class FavoritesButtonBinding
    : MvxBaseAndroidTargetBinding
{
    private readonly Button _button;
    private bool _currentValue;

    public FavoritesButtonBinding(Button button)
    {
        _button = button;
        _button.Click += ButtonOnClick;
    }

    private void ButtonOnClick(object sender, EventArgs eventArgs)
    {
        _currentValue = !_currentValue;
        SetButtonBackground();
        FireValueChanged(_currentValue);
    }

    public override void SetValue(object value)
    {
        var boolValue = (bool)value;
        _currentValue = boolValue;
        SetButtonBackground();
    }

    private void SetButtonBackground()
    {
        if (_currentValue)
        {
            _button.SetBackgroundResource(Resource.Drawable.star_gold_selector);
        }
        else
        {
            _button.SetBackgroundResource(Resource.Drawable.star_grey_selector);
        }
    }

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            _button.Click -= ButtonOnClick;
        }
        base.Dispose(isDisposing);
    }

    public override Type TargetType
    {
        get { return typeof(bool); }
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }
}
like image 143
Stuart Avatar answered Sep 19 '22 00:09

Stuart