【问题标题】:MvvmCross UITextField custom bindingMvvmCross UITextField 自定义绑定
【发布时间】:2014-03-11 07:54:16
【问题描述】:

所以我正在尝试为 MvvmCross 中的 UITextField 实现自定义绑定,几乎与Binding 'GO' key on Software Keyboard 类似 - 即尝试绑定文本字段以在点击键盘上的“完成”按钮时自动触发事件(所以绑定到ShouldReturn)。我还需要绑定文本字段的EditingDidBeginEditingDidEnd 事件。因为我绑定了多个事件,所以我创建了一个MvxPropertyInfoTargetBinding,如下:

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 Binding decimal to UITextField removes decimal point,前者用于替换现有绑定,后者用于已知属性和事件对。那么我使用的是正确的吗?

其次(也是我的问题的真正症结所在),我的代码除了 SetValue - 它被解雇了,但valuenull。这是我在Setup 文件中的内容:

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

我没有在我的View 中做任何事情 - 也许这就是问题所在?

编辑:

我的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 中创建视图元素):

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

没有有趣的 Trace 消息。

【问题讨论】:

  • 您能否编辑问题以包括:绑定代码、您要绑定的视图模型属性以及您在绑定期间看到的任何相关或令人担忧的跟踪?
  • 完成。感谢您对此进行调查!
  • Argh - 刚刚写了寻找答案,我的手机吃掉了它:/稍后回来

标签: c# xamarin.ios mvvmcross


【解决方案1】:

1。 PropertyInfoTargetBinding 有什么特别之处?

您引用的问题 - MVVMCross Binding decimal to UITextField removes decimal point - 给出了 MvxTargetBindingMvxPropertyInfoTargetBinding 之间区别的关键:

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

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

替换现有绑定时使用前者

这绝对不是真的——相反,任何绑定都可以用来替换另一个绑定——正如另一个问题的答案所说

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

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


2。为什么我的 SetValue 为空?

您当前的绑定代码要求 ICommand:

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

但是您的视图代码当前正在将视图绑定到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. 更改视图和绑定以反映这一点。

【讨论】:

  • 谢谢。我通过使用MvxTargetBinding(基本上使用Binding 'GO' key on Software Keyboard 中使用的实现)解决了这个问题,并将我的View 中的绑定代码更改为:set.Bind(usernameTextField).To(vm =&gt; vm.Username); set.Bind(passwordTextField).To(vm =&gt; vm.Password); set.Bind(passwordTextField).For("ShouldReturn").To(vm =&gt; vm.Login);(我不知道您可以绑定一个字段两次!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
相关资源
最近更新 更多