MvvmCross Monotouch C#-绑定Int属性-模式:TwoWay [英] MvvmCross Monotouch C# - Binding Int Property - Mode: TwoWay
问题描述
我是MvvmCross的新手,我有一个问题.
I am new to MvvmCross and I have a question.
我注意到以下绑定代码仅以一种方式起作用:
I noticed that the following binding code works in one way only:
{ this, "{'CurrentIndex':{'Path':'CurrentIndex','Mode':'TwoWay'}}" }
- CurrentIndex是视图中的Int属性
- CurrentIndex也是ViewModel中的Int属性
- ViewModel =>视图
- View => ViewModel
- 在您的活动(MyActivity)中声明一个事件-CurrentIndexChanged-每当CurrentIndex更改时都会触发
- 为MyActivity声明自定义绑定,该绑定以编程方式链接CurrentIndex和CurrentIndexChanged
- 在安装过程中将自定义绑定添加到绑定注册表中
这种方式有效!
但不是这样!
我有一个ViewControllers集合,我的目标是在viewModel中为CurrentIndex调用DeleteCommand.
I have a collection of ViewControllers and my goal was to call a DeleteCommand for the CurrentIndex in the viewModel.
但是
"Android和Touch 2方式绑定不完整"
"Android and Touch 2 way bindings are incomplete"
我的猜测是,双向模式仅适用于控件(UILabel,UITextfield等),不适用于属性.
My guess is the TwoWay mode only works for Controls (UILabel, UITextfield, ...) but not for Properties.
那么,有没有一种好的方法可以使它同时起作用呢?还是我的问题有其他选择吗?
So, is there a good way to make it works in both ways? Or Are there any alternatives to my problem?
帕特里克
推荐答案
为了使绑定在View和ViewModel之间传输任何值,则当值更改时,它需要挂接到某个事件中.
In order for a binding to transfer any value between a View to a ViewModel, then it needs to hook into some event when the value changes.
在ViewModel中,此事件始终是INotifyProperty接口中的事件.
In the ViewModel, this event is always the event in the INotifyProperty interface.
在视图/活动"中,使用了一个单一模式-因此每个绑定都必须挂接到一个单独的事件中.例如,使用TextChanged事件连接EditText上的Text(请参见 MvxSeekBarProgressTargetBinging.cs ).
In the View/Activity, there is one single pattern employed - so each binding has to hook into a separate event. For example, the Text on EditText is hooked up using the TextChanged event (see MvxEditTextTextTargetBinding.cs) while the value in a SeekBar is hooked up using a Listener object rather than an event (see MvxSeekBarProgressTargetBinging.cs).
因此,如果您想为您的活动实现这种双向绑定,则可以通过以下方式实现:
So if you wanted to implement this two-way binding for your activity, then you could do this by:
例如,您的活动可能包括:
For example, your activity might include:
public event EventHandler CurrentIndexChanged;
private int _currentIndex;
public int CurrentIndex
{
get { return _currentIndex; }
set { _currentIndex = value; if (CurrentIndexChanged != null) CurrentIndexChanged(this, EventArgs.Empty); }
}
然后您可以声明一个绑定类,如:
And you might then declare a binding class like:
public class MyBinding : MvxPropertyInfoTargetBinding<MyActivity>
{
public MyBinding (object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
View.CurrentIndexChanged += OnCurrentIndexChanged;
}
public override MvxBindingMode DefaultMode
{
get
{
return MvxBindingMode.TwoWay;
}
}
private void OnCurrentIndexChanged(object sender, EventArgs ignored)
{
FireValueChanged(View.CurrentIndex);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
View.CurrentIndexChanged -= OnCurrentIndexChanged;
}
}
}
您需要通过以下方式告知绑定系统有关此绑定的信息:
And you'd need to tell the binding system about this binding in setup like:
registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(MyBinding), typeof(MyActivity), "CurrentIndex"));
但是...在实践上,如果您使用C#而不是XML进行操作,那么在这种情况下,最好使用C#来简单地更新ViewModel,而不是在这种情况下使用声明性绑定.
However... at a practical level, if you are operating in C# rather than in XML, then you might be better off in this case using C# to simply update the ViewModel rather than using declarative binding in this case.
要清楚...在这种情况下,我很可能只是将Activity属性写为:
To be clear... in this case, I would most probably just write the Activity property as:
public int CurrentIndex
{
get { return _currentIndex; }
set { _currentIndex = value; ViewModel.CurrentIndex = value; }
}
或者...我会考虑完全不在Activity中使用此属性.
Or... I'd consider not having this property in the Activity at all.
如果有帮助,请参见以下有关自定义绑定的更多信息:
If it helps, there's some more information on custom bindings in:
- MonoTouch MVVMCross binding to instance variables
- In MvvmCross how do I do custom bind properties
希望这会有所帮助!恕我直言,在使用XML时,绑定可以为您提供帮助-您不必使用它们...
Hope this helps! IMHO the bindings are there to help you when you're working in XML - you don't have to use them...
斯图尔特
更新如果要执行许多操作并遵循相同的名称模式,请使用名为 X 的属性以及已更改的名为 XChanged 然后类似的事情可能会起作用-它使用反射来自动找到事件:
UPDATE If you are going to do lots of these and follow the same name pattern - using property named X with changed EventHandler event named XChanged then something like this might work - it uses reflection to find the event automagically:
public class MyBinding<T> : MvxPropertyInfoTargetBinding<T>
where T : class
{
private readonly PropertyInfo _propertyInfo;
private readonly EventInfo _eventInfo;
public MyBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
_propertyInfo = targetPropertyInfo;
var eventName = _propertyInfo.Name + "Changed";
_eventInfo = View.GetType().GetEvent(eventName);
if (_eventInfo == null)
{
throw new MvxException("Event missing " + eventName);
}
if (_eventInfo.EventHandlerType != typeof(EventHandler))
{
throw new MvxException("Event type mismatch for " + eventName);
}
var addMethod = _eventInfo.GetAddMethod();
addMethod.Invoke(View, new object[] { new EventHandler(OnChanged) });
}
public override MvxBindingMode DefaultMode
{
get
{
return MvxBindingMode.TwoWay;
}
}
private void OnChanged(object sender, EventArgs ignored)
{
var value = _propertyInfo.GetValue(View, null);
FireValueChanged(value);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var removeMethod = _eventInfo.GetRemoveMethod();
removeMethod.Invoke(View, new object[] { new EventHandler(OnChanged) });
}
}
}
这篇关于MvvmCross Monotouch C#-绑定Int属性-模式:TwoWay的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!