Binding 'GO' key on Software Keyboard

Tag: monotouch , xamarin , mvvmcross Author: chengxi59420 Date: 2013-10-02

I've got a log-in button bound to a command that exists inside my ViewModel like so:

this.AddBindings(new Dictionary<object, string>{{btnLogin,"TouchUpInside LoginCommand"}});

The software keyboard is suppressed if a touch is made, somewhere outside the keyboard or UITextField. To prevent the user from having to click once somewhere on the screen to make the keyboard disappear and then pressing the log-in button, I would like to associate the log-in command defined in the ViewModel to the 'GO' key in the keyboard. Is this possible?

Best Answer

The simple solution is the one given in the previous answer.

However, if you wanted to go further, then you could add a custom binding, implemented something like:

public class MvxUITextFieldShouldReturnTargetBinding
    : MvxTargetBinding
{
    private ICommand _command;

    protected UITextField View
    {
        get { return Target as UITextField; }
    }

    public MvxUITextFieldShouldReturnTargetBinding(UITextField target)
        : base(target)
    {
        target.ShouldReturn = HandleShouldReturn;
    }

    private bool HandleShouldReturn(UITextField textField)
    {
        if (_command == null)
            return false;

        var text = textField.Text;
        if (!_command.CanExecute(text))
            return false;

        textField.ResignFirstResponder();
        _command.Execute(text);
        return true;
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.OneWay; }
    }

    public override void SetValue(object value)
    {
        var command = value as ICommand;
        _command = command;
    }

    public override System.Type TargetType
    {
        get { return typeof(ICommand); }
    }


    protected override void Dispose(bool isDisposing)
    {
        base.Dispose(isDisposing);
        if (isDisposing)
        {
            var editText = View;
            if (editText != null)
            {
                editText.ShouldReturn = null;
            }
        }
    }
}

which you could register during setup as:

        registry.RegisterCustomBindingFactory<UITextField>("ShouldReturn",
                                                           textField => new MvxUITextFieldShouldReturnTargetBinding(textField));

I think that would work - it should allow you to bind a MvxCommand or an MvxCommand<string>

For more on custom bindings, see N=28 in http://mvvmcross.wordpress.com

Other Answer1

You can't bind the button itself. This is dependent on the focused UIView which triggers the keyboard to have the GO button. I.e. if it is a UITextField you can assign a function or delegate to the ShouldReturn property, which then triggers your LoginCommand. Something like:

myUiTextField.ShouldReturn += delegate
    {
        ViewModel.LoginCommand.Execute(null);
        return true;
    };

Read more about the property in the Xamarin.iOS API documentation.

comments:

Small note, the return of a boolean is expected: myUiTextField.ShouldReturn += (textField) => { CurrentViewModel.LoginCommand.Execute(null); return true; };