MvvmCross UITextField自定义绑定
所以我试图在MvvmCross中为UITextField实现自定义绑定,几乎与软件键盘上的 Binding’GO ‘键一致 – 即尝试绑定文本字段以在点击完成按钮时自动触发事件键盘(因此绑定到ShouldReturn
)。 我还需要绑定文本字段的EditingDidBegin
和EditingDidEnd
事件。 因为我绑定了多个事件,所以我创建了一个MvxPropertyInfoTargetBinding
,如下所示:
public class MyTextFieldTargetBinding : MvxPropertyInfoTargetBinding { 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
? 相关地,我没有区分MvxPropertyInfoTargetBinding
和MvxTargetBinding
。 根据MVVMCross Binding decimal到UITextField删除小数点 ,前者在替换现有绑定时使用,后者用于已知属性和事件对。 我使用正确的吗?
其次(以及我的问题的真正关键),我的代码除 SetValue
外有效 – 它被触发,但value
null
。 这是我在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中创建了View元素):
public override void ViewDidLoad() { base.ViewDidLoad (); this.NavigationController.SetNavigationBarHidden(true, false); var set = this.CreateBindingSet(); 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删除小数点 – 给出了MvxTargetBinding
和MvxPropertyInfoTargetBinding
之间差异的关键:
- TargetBinding可用于任何任意绑定 – 例如,用于
a non-propertyInfo-based binding
- PropertyInfoTargetBindinginheritance自TargetBinding,只能与实际的C#属性一起使用 – 因为它通过Reflection使用PropertyInfo。
在你的情况下,因为你实际上并没有通过Reflection使用Text
属性,所以我很想不使用PropertyInfoTargetBinding并避开Text
名称 – 而只是编写一个自定义TargetBinding。
替换现有绑定时使用前者
这绝对不是真的 – 相反,任何绑定都可以用来替换另一个绑定 – 正如另一个问题的答案所说的那样
MvvmCross运营着一个简单的“最后注册胜利”系统
有关自定义绑定的更多信息,请查看:
- http://mvvmcross.blogspot.co.uk/中的N = 28video
- 看一下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
- 请注意,其中大多数使用MvxPropertyInfoTargetBinding或MvxConvertingTargetBinding作为基类
2.为什么我的SetValue变为空?
您当前的绑定代码要求ICommand:
public override Type TargetType { get { return typeof(ICommand); } }
但是您的View代码当前将View绑定到string
:
// View set.Bind(usernameTextField).To(vm => vm.Username); // ViewModel private string _username; public string Username { get { return _username; } set { _username = value; RaisePropertyChanged(() => Username); } }
解决这个问题……
- 找出你想要绑定的东西 – 它是一个ICommand(例如和MvxCommand)还是一个
string
? - 更改视图和绑定以反映这一点。