2013-08-29 53 views
1

在使用MvvmCross框架构建的跨平台Xamarin应用程序中,我在Android .axml布局中使用了ToggleButton Widget。我已使用转换器使用以下绑定语法将Checked属性绑定到View Model属性:MvvmCross和UIButton.Selected UISegmentedControl绑定,iOS

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支持的此控件?我没有在源代码中看到它的任何引用。这是否意味着我需要为它创建自定义绑定?

回答

1

对于UIButton,我不认为在MvvmCross中内置了任何包含Selected的绑定。因为这个 - 因为Selected没有简单的配对事件SelectedChanged,那么我认为Selected绑定应该单向工作(从ViewModel到View)而不是双向工作。

UISwitch控件的On有一个绑定,这是我在这些情况下使用最多的控件。


如果你想添加自定义2路为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绑定将是相当直接的 - 你只需要绑定到SelectedSegmentValueChanged - 与上面类似的代码。

或者,您可以切换到使用自定义MySegmentedControl它有一个更好的Value`ValueChanged`一对会不自定义绑定自动工作 - 例如:

public class MySegmentedControl : UISegmentedControl 
    { 
     // add more constructors if required 

     public int Value 
     { 
      get { return base.SelectedSegment; } 
      set { base.SelectedSegment = value; } 
     } 
    } 

如果任何或所有这些自定义绑定的需要,那么MVX项目是高兴得到这些绑定添加问题或https://github.com/slodge/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs项目,测试/演示的用户界面拉请求一起

1

可能对别人有帮助,所以我分享了我的经验。我需要一个双向绑定UISegmentedControl.SelectedSegment属性到ViewModel。单向标记(ViewModel => 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"); 
    } 
}