在使用MvvmCross框架构建的跨平台Xamarin应用程序中,我在Android .axml布局中使用了ToggleButton小部件。我使用以下绑定语法使用转换器将Checked属性绑定到View Model属性:
Checked MarketBuySellViewModel.Direction, Converter=DirectionBool, ConverterParameter='Sell'
一切都运作良好。在iOS端,看起来您可以使用Selected属性将UIButton用作ToggleButton。这意味着以下绑定应该实现我想要的iOS:
set.Bind (SellButton).For(b => b.Selected).To (vm => vm.MarketBuySellViewModel.Direction).WithConversion("DirectionBool", "Sell");
我在应用程序输出中没有遇到任何绑定错误,但绑定本身似乎不起作用。单击该按钮不会设置Direction属性,将方向设置为其他值不会在UIButton上设置Selected属性。
我是否需要创建自定义绑定,或者我只是错误地设置绑定?
我也尝试使用UISegmentedControl来达到同样的效果。在MvvmCross中是否支持绑定到此控件?我在源代码中没有看到任何对它的引用。这是否意味着我还需要为它创建自定义绑定?
答案 0 :(得分:1)
对于UIButton,我不相信MvvmCross中包含的任何Selected
绑定。因此 - 并且因为Selected
没有简单的配对事件SelectedChanged
,所以我认为Selected
绑定应该单向工作(从ViewModel到View),但不是两个三通。
对On
UISwitch
控件的Selected
有绑定,而且我在这些情况下看到的控件使用最多。
如果您想为ValueChanged
添加自定义双向绑定,那么我猜测您必须使用public class MvxUIButtonSelectedTargetBinding : MvxPropertyInfoTargetBinding<UIButton>
{
public MvxUIButtonSelectedTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var view = View;
view.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = View;
if (view == null)
return;
FireValueChanged(view.Selected);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
事件执行此操作(但是需要检查是否正确)。
为此,您只需构建一个目标绑定,例如:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
这可以使用以下内容在registry.RegisterPropertyInfoBindingFactory(typeof(MvxUIButtonSelectedTargetBinding), typeof(UIButton),
"Selected");
中的安装程序中注册:
UISegmentedControl
同样地,我不相信任何人已经添加了双向UISegmentedControl
绑定 - 但很高兴看到有人加入。
构建双向SelectedSegment
绑定非常简单 - 您只需绑定到ValueChanged
和MySegmentedControl
对 - 代码与上面类似。
或者,您可以切换到使用具有更好 Value
`ValueChanged`对的自定义 public class MySegmentedControl : UISegmentedControl
{
// add more constructors if required
public int Value
{
get { return base.SelectedSegment; }
set { base.SelectedSegment = value; }
}
}
,该对将在没有自定义绑定的情况下自动工作 - 例如:
{{1}}
如果需要任何或所有这些自定义绑定,那么Mvx项目很乐意将这些绑定添加为问题或拉取请求以及https://github.com/slodge/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs项目中的测试/演示UI
答案 1 :(得分:1)
可能对其他人有所帮助,所以我可以分享我的经验。我需要将UISegmentedControl.SelectedSegment属性双向绑定到ViewModel。单向绑定(ViewModel =&gt; View)默认工作。我无法正确利用Stuart提出的解决方案来继承UISegmentedControl。我试图确保链接器不会破坏新的自定义控制代码,但这对我没什么帮助。因此,一个完全可行的解决方案是使用MvxPropertyInfoTargetBinding的解决方案。这是适合我的代码:
public class MvxUISegmentedControlSelectedSegmentTargetBinding : MvxPropertyInfoTargetBinding<UISegmentedControl>
{
public MvxUISegmentedControlSelectedSegmentTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
this.View.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = this.View;
if (view == null)
{
return;
}
FireValueChanged(view.SelectedSegment);
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
var view = this.View;
if (view != null)
{
view.ValueChanged -= HandleValueChanged;
}
}
}
}
public class Setup : MvxTouchSetup
{
...
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterPropertyInfoBindingFactory(typeof(MvxUISegmentedControlSelectedSegmentTargetBinding), typeof(UISegmentedControl), "SelectedSegment");
}
}