MvvmCross UITextField自定义绑定 [英] MvvmCross UITextField custom binding

查看:68
本文介绍了MvvmCross UITextField自定义绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我试图在MvvmCross中实现UITextField的自定义绑定,大致类似于-即尝试在键盘上轻按完成"按钮时绑定文本字段以自动触发事件(因此绑定到ShouldReturn).我还需要绑定文本字段的EditingDidBeginEditingDidEnd事件.因为我绑定了多个事件,所以创建了一个MvxPropertyInfoTargetBinding,如下所示:

So I am trying to implement a custom binding for a UITextField in MvvmCross, pretty much along the lines of Binding 'GO' key on Software Keyboard - i.e. trying to bind a text field to automatically fire an event when the Done button is tapped on the keyboard (so binding to ShouldReturn). I also need to bind the text field's EditingDidBegin and EditingDidEnd events. Because I am binding more than one event, I have created a MvxPropertyInfoTargetBinding as follows:

public class MyTextFieldTargetBinding : MvxPropertyInfoTargetBinding<UITextField>
{
    private ICommand _command;

    protected UITextField TextField
    {
        get { return (UITextField)Target; }
    }

    public MyTextFieldTargetBinding(object target, PropertyInfo targetPropertyInfo) : base(target, targetPropertyInfo)
    {
        TextField.ShouldReturn += HandleShouldReturn;
        TextField.EditingDidBegin += HandleEditingDidBegin;
        TextField.EditingDidEnd += HandleEditingDidEnd;
    }

    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;
    }

    private void HandleEditingDidBegin (object sender, EventArgs e)
    {
        // do something
    }

    private void HandleEditingDidEnd (object sender, EventArgs e)
    {
        // do something
    }

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

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

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

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            if (TextField != null)
            {
                TextField.ShouldReturn -= HandleShouldReturn;
                TextField.EditingDidBegin -= HandleEditingDidBegin;
                TextField.EditingDidEnd -= HandleEditingDidEnd;
            }
        }

        base.Dispose(isDisposing);
    }

}

我的第一个问题是:为所有事件创建一个MvxPropertyInfoTargetBinding正确吗?相关地,我没有得到MvxPropertyInfoTargetBindingMvxTargetBinding之间的区别.根据 MVVMCross将十进制绑定到UITextField会删除小数点在替换现有绑定时使用绑定",后者用于已知属性和事件对.那我使用的是正确的吗?

My first question is: am I correct in creating one MvxPropertyInfoTargetBinding for all the events? Relatedly, I don't get the difference between MvxPropertyInfoTargetBinding and MvxTargetBinding. According to MVVMCross Binding decimal to UITextField removes decimal point the former is used when replacing an existing binding, the latter for known properties and event pairs. So am I using the correct one?

其次(也是我问题的真正症结),我的代码除了 SetValue外均有效-已被触发,但valuenull.这是我的Setup文件中的内容:

Secondly (and the real crux of my problem), my code works except for SetValue - it is fired, but the value is null. Here is what I have in my Setup file:

protected override void FillTargetFactories (IMvxTargetBindingFactoryRegistry registry)
{
    base.FillTargetFactories (registry);
    registry.RegisterPropertyInfoBindingFactory(typeof(MyTextFieldTargetBinding), typeof(UITextField), "Text");
}

我在View中什么也没做-也许这就是问题所在?

I don't do anything in my View - perhaps that is where the issue lies?

我的ViewModel:

public class LoginViewModel : MvxViewModel
{
    private string _username;
    public string Username
    { 
        get { return _username; }
        set { _username = value; RaisePropertyChanged(() => Username); }
    }

    private string _password;
    public string Password
    { 
        get { return _password; }
        set { _password = value; RaisePropertyChanged(() => Password); }
    }

    private MvxCommand _login;
    public ICommand Login
    {
        get {
            _login = _login ?? new MvxCommand(DoLogin);
            return _login;
        }
    }

    public LoginViewModel(ILoginManager loginManager)
    {
        _loginManager = loginManager;
    }

    private void DoLogin()
    {
        // call the login web service
    }
}

在我的视图"中,我没有做任何花哨的事情(我确实在XIB中创建了View元素):

In my `View', I don't do anything fancy (I do create the View elements in a XIB):

public override void ViewDidLoad()
{
    base.ViewDidLoad ();

    this.NavigationController.SetNavigationBarHidden(true, false);

    var set = this.CreateBindingSet<LoginView, Core.ViewModels.LoginViewModel>();
    set.Bind(usernameTextField).To(vm => vm.Username);
    set.Bind(passwordTextField).To(vm => vm.Password);
    set.Bind (loginButton).To (vm => vm.Login);
    set.Apply();
}

没有有趣的跟踪消息.

推荐答案

1. PropertyInfoTargetBinding有什么特别之处?

您引用的问题- MVVMCross将十进制绑定到UITextField会删除小数点-给出MvxTargetBindingMvxPropertyInfoTargetBinding之间的区别的键:

1. What is special about PropertyInfoTargetBinding?

The question you reference - MVVMCross Binding decimal to UITextField removes decimal point - gives the key to the difference between MvxTargetBinding and MvxPropertyInfoTargetBinding:

  • TargetBinding可用于任何任意绑定-例如对于a non-propertyInfo-based binding
  • PropertyInfoTargetBinding继承自TargetBinding,并且只能与实际的C#属性一起使用-因为它通过反射使用PropertyInfo.

在您的情况下,由于您实际上并没有通过反射使用Text属性,所以我很想使用PropertyInfoTargetBinding并避开Text名称以及-只需编写自定义TargetBinding.

In your case, since you aren't actually using the Text property via Reflection, then I'd be tempted not to use a PropertyInfoTargetBinding and to steer clear of the Text name as well - instead just write a custom TargetBinding.

在替换现有绑定时使用前者

the former is used when replacing an existing binding

绝对不正确-可以使用任何绑定来替换另一个绑定-另一个问题的答案是

This is definitely not true - instead any binding can be used to replace another binding - as the answer on the other question says

MvvmCross运行一个简单的最后注册的获胜者"系统

MvvmCross operates a simple 'last registered wins' system

有关自定义绑定的更多信息,请查看:

For more on custom bindings, take a look at:

  • http://mvvmcross.blogspot.co.uk/中的N = 28个视频
  • 看一下MvvmCross附带的一些标准"绑定
    • the N=28 video in http://mvvmcross.blogspot.co.uk/
    • take a look through some of the "standard" bindings that ship with MvvmCross
      • Droid - https://github.com/MvvmCross/MvvmCross/tree/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Droid/Target
      • iOS - https://github.com/MvvmCross/MvvmCross/tree/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Touch/Target
      • note that most of these use either MvxPropertyInfoTargetBinding or MvxConvertingTargetBinding as a base class

      您当前的绑定代码正在请求ICommand:

      Your current binding code is asking for an ICommand:

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

      但是您的View代码当前正在将View绑定到string:

      But your View code is currently binding the View to a string:

      // View
      set.Bind(usernameTextField).To(vm => vm.Username);
      
      // ViewModel
      private string _username;
      public string Username
      { 
          get { return _username; }
          set { _username = value; RaisePropertyChanged(() => Username); }
      }
      

      要解决此问题...

      1. 计算出要绑定的内容-是ICommand(例如,MvxCommand)还是string?
      2. 更改视图和绑定以反映这一点.

      这篇关于MvvmCross UITextField自定义绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆