bindingxamarin.androidmvvmcrossmvxbind

mvvmcross MvxBind on actionSend (imeOption action)


i have an editText like this:

    <EditText
        local:MvxBind="Text MyProperty; Click MyCommand"
        android:inputType="textShortMessage"
        android:imeOptions="actionSend" />

I want the command to be triggered by the "enter/action" key on the keyboard. What verb should i use in the binding ? The "Change" verb i currently use triggers on any touch in the control !(


Solution

  • If you want to implement a "custom binding", then there are 3 types of way to do it:

    1. Implement and register a true custom binding
    2. Implement a custom control which exposes a custom property to bind to
    3. Use an intermediate object which exposes a custom property

    The answer in https://stackoverflow.com/a/19221385/373321 shows a true custom binding.


    Custom controls which inherit from standard views is discussed in N=18 in http://mvvmcross.blogspot.com - an example here might be:

    public class DoneEditText : EditText, TextView.IOnEditorActionListener
    {
        public DoneEditText(Context context) : base(context)
        {
            Init();
        }
    
        public DoneEditText(Context context, IAttributeSet attrs) : base(context, attrs)
        {
            Init();
        }
    
        public DoneEditText(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
        {
            Init();
        }
    
        private void Init()
        {
              this.SetOnEditorActionListener(this);
        }
    
        public ICommand DoneAction { get;set; ]
    
        #region Implementation of IOnEditorActionListener
    
        public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
        {
            if (actionId == ImeAction.Done)
            {
                if (DoneAction != null)
                        DoneAction.Execute(v.Text);
                return true;
            }
    
            return false;
        }
    
        #endregion
    }    
    

    Using an intermediate object for the binding would use a class like:

    public class DoneActionListener : Java.Lang.Object, TextView.IOnEditorActionListener
    {
        public ICommand DoneAction { get; set; }
    
        public DoneActionListener(TextView v)
        {
              v.SetOnEditorActionListener(this);
       }
    
        #region Implementation of IOnEditorActionListener
    
        public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
        {
            if (actionId == ImeAction.Done)
            {
                if (DoneAction != null)
                        DoneAction.Execute(v.Text);
                return true;
            }
    
            return false;
        }
    
        #endregion
    }
    

    this could be handled in OnCreate using Fluent Binding like:

    private DoneActionListener _listener;
    
    public override OnCreate(Bundle b)
    {
        base.OnCreate(b);
        SetContentView(Resource.Layout.MyLayoutId);
    
        _listener = new DoneActionListener(FindViewById<EditText>(Resource.Id.MyEditId));
    
        var set = this.CreateBindingSet<MyView, MyViewModel>();
        set.Bind(_listener).For(v => v.DoneAction).To(vm => vm.TheDoneCommand);
        set.Apply();
    }