为了让绑定在 View 和 ViewModel 之间传输任何值,它需要在值更改时挂钩到某个事件。
在 ViewModel 中,此事件始终是 INotifyProperty 接口中的事件。
在视图/活动中,使用了一个单一的模式——因此每个绑定都必须挂钩到一个单独的事件中。例如,EditText 上的 Text 使用 TextChanged 事件(参见MvxEditTextTextTextTargetBinding.cs)连接,而 SeekBar 中的值使用 Listener 对象而不是事件连接(参见MvxSeekBarProgressTargetBinging.cs)。
因此,如果您想为您的活动实现这种双向绑定,那么您可以通过以下方式执行此操作:
- 在您的活动 (MyActivity) 中声明一个事件 - CurrentIndexChanged - 只要 CurrentIndex 更改就会触发
- 为您的 MyActivity 声明一个自定义绑定,它以编程方式链接 CurrentIndex 和 CurrentIndexChanged
- 在安装过程中将自定义绑定添加到绑定注册表
例如,您的活动可能包括:
public event EventHandler CurrentIndexChanged;
private int _currentIndex;
public int CurrentIndex
{
get { return _currentIndex; }
set { _currentIndex = value; if (CurrentIndexChanged != null) CurrentIndexChanged(this, EventArgs.Empty); }
}
然后你可以声明一个绑定类,如:
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;
}
}
}
您需要在设置中告诉绑定系统有关此绑定的信息,例如:
registry.RegisterFactory(new MvxSimplePropertyInfoTargetBindingFactory(typeof(MyBinding), typeof(MyActivity), "CurrentIndex"));
但是...在实际层面上,如果您使用 C# 而不是 XML 进行操作,那么在这种情况下使用 C# 来简单地更新 ViewModel 而不是在这种情况下使用声明性绑定可能会更好。
要清楚......在这种情况下,我很可能只是将 Activity 属性写为:
public int CurrentIndex
{
get { return _currentIndex; }
set { _currentIndex = value; ViewModel.CurrentIndex = value; }
}
或者......我会考虑在 Activity 中根本没有这个属性。
如果有帮助,还有更多关于自定义绑定的信息:
希望这可以帮助!恕我直言,当您使用 XML 时,绑定可以帮助您 - 您不必使用它们...
斯图尔特
更新如果您要执行很多这些操作并遵循相同的名称模式 - 使用名为X的属性和名为XChanged的已更改 EventHandler 事件,那么这样的事情可能会起作用 - 它使用反射自动查找事件:
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) });
}
}
}