1

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

4

2 回答 2

1

对于 UIButton,我不相信SelectedMvvmCross 中内置了任何包含的绑定。正因为如此 - 因为Selected没有简单的配对事件SelectedChanged,所以我相信Selected绑定应该单向工作(从 ViewModel 到 View)而不是双向工作。

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


如果您想添加自定义的 2-way 绑定,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更好的“ValueChanged”对的自定义,无需 Value自定义绑定即可自动工作 - 例如:

    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中的测试/演示 UI /master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs项目

于 2013-08-29T14:32:37.680 回答
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");
    }
}
于 2014-11-04T08:06:31.217 回答