MvvmCross Monotouch C#-绑定Int属性-模式:双向
我是MvvmCross的新手,我有一个问题 我注意到以下绑定代码仅以一种方式工作:MvvmCross Monotouch C#-绑定Int属性-模式:双向,mvvm,xamarin.ios,mvvmcross,Mvvm,Xamarin.ios,Mvvmcross,我是MvvmCross的新手,我有一个问题 我注意到以下绑定代码仅以一种方式工作: { this, "{'CurrentIndex':{'Path':'CurrentIndex','Mode':'TwoWay'}}" } CurrentIndex是视图中的一个Int属性 CurrentIndex也是ViewModel中的一个Int属性 这条路行得通 ViewModel=>View 但不是这样 视图=>ViewModel 我有一个ViewController集合,我的目标是为view
{ this, "{'CurrentIndex':{'Path':'CurrentIndex','Mode':'TwoWay'}}" }
- CurrentIndex是视图中的一个Int属性
- CurrentIndex也是ViewModel中的一个Int属性
- ViewModel=>View
- 视图=>ViewModel
Patrick为了让绑定在视图和ViewModel之间传输任何值,那么当值发生变化时,它需要挂接到某个事件中 在ViewModel中,此事件始终是INotifyProperty界面中的事件 在视图/活动中,使用了一种模式,因此每个绑定都必须挂接到一个单独的事件中。例如,EditText上的文本使用TextChanged事件连接(请参阅),而SeekBar中的值使用侦听器对象而不是事件连接(请参阅) 因此,如果您想为您的活动实现这种双向绑定,那么您可以通过以下方式实现:
- 在活动(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;
}
}
}
然而。。。在实际层面上,如果您是在C#而不是在XML中操作,那么在本例中最好使用C#来简单地更新ViewModel,而不是在本例中使用声明性绑定 说清楚。。。在这种情况下,我很可能只将Activity属性写为:
public int CurrentIndex
{
get { return _currentIndex; }
set { _currentIndex = value; ViewModel.CurrentIndex = value; }
}
或者。。。我认为在活动中没有这个属性。
如果有帮助的话,下面是有关自定义绑定的更多信息:
希望这有帮助!当您使用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) });
}
}
}
公共类MyBinding:MvxPropertyInfoTargetBinding
T:在哪里上课
{
私有只读属性yinfo_PropertyInfo;
私有只读事件信息\u事件信息;
公共MyBinding(对象目标,PropertyInfo目标PropertyInfo)
:base(目标、targetPropertyInfo)
{
_propertyInfo=目标propertyInfo;
var eventName=_propertyInfo.Name+“已更改”;
_eventInfo=View.GetType().GetEvent(eventName);
如果(_eventInfo==null)
{
抛出新的MvxException(“事件丢失”+eventName);
}
if(_eventInfo.EventHandlerType!=typeof(EventHandler))
{
抛出新的MvxException(“事件类型与“+eventName”不匹配);
}
var addMethod=_eventInfo.GetAddMethod();
Invoke(视图,新对象[]{neweventhandler(OnChanged)});
}
公共覆盖MvxBindingMode默认模式
{
得到
{
返回MvxBindingMode.TwoWay;
}
}
私有void一旦更改(对象发送方,事件参数被忽略)
{
var value=_propertyInfo.GetValue(视图,null);
FireValueChanged(值);
}
受保护的覆盖无效处置(bool isDisposing)
{
基础处理(isDisposing);
if(isDisposing)
{
var removeMethod=_eventInfo.GetRemoveMethod();
调用(视图,新对象[]{neweventhandler(OnChanged)});
}
}
}
@Stuart,在上面的示例中,CurrentIndex是int类型,MyBinding要求T是引用类型。如何使用更新的答案?@Stuart,registry.RegisterFactory(新的MvxSimplePropertyInfoTargetBindingFactory(typeof(MyBinding),typeof(MyActivity),“CurrentIndex”);MyBinding中的错误
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) });
}
}
}