Thursday, May 10, 2012

Adding custom bindings in MvvmCross for Android/MonoDroid


The MvvmCross binding framework automatically adds one-way bind (from ViewModel to View) to all existing public Properties on any MonoDroid/Android 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 a 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; }
    }
}

No comments:

Post a Comment