Проблема с привязкой BEMCheckBox к ViewModel - MvvmCross, Xamarin. iOS - PullRequest
0 голосов
/ 05 мая 2020

Я новичок в MvvmCross и все еще пытаюсь понять, как это делается. Я использую BEMCheckBox для одного из моих разрабатываемых приложений, и я попытался привязать свойство «On» BEMCheckBox к ViewModel. К сожалению, это не работает должным образом.

BEMCheckBox Github: https://github.com/saturdaymp/XPlugins.iOS.BEMCheckBox NuGet: SaturdayMP.XPlugins. iOS .BEMCheckBox Версия: 1.4.3

MvvmCross Версия: 6.4.2

Это мой класс просмотра

[MvxFromStoryboard("Main")]
[MvxRootPresentation(WrapInNavigationController = false)]
public partial class MyView : BaseView<MyViewModel>
{
    private BEMCheckBox CheckBox;

    public MyView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        //add check box
        CheckBox = new BEMCheckBox(new CoreGraphics.CGRect(0, 0, 20, 20))
        {
            BoxType = BEMBoxType.Square,
            TintColor = UIColor.FromRGBA(0, 0, 0, 0.14f),
            OnFillColor = UIColor.FromRGB(42, 183, 202),
            OnCheckColor = UIColor.White,
            OnTintColor = UIColor.FromRGBA(0, 0, 0, 0.14f),
            OnAnimationType = BEMAnimationType.Bounce,
            OffAnimationType = BEMAnimationType.Bounce,
            On = false,
            CornerRadius = 0,
        };

        //CheckBoxContainerView is an UIView 
        CheckBoxContainerView.AddSubview(CheckBox);
        CheckBoxContainerView.BackgroundColor = UIColor.Clear;

        //Binding to View Model
        var set = this.CreateBindingSet<MyView, MyViewModel>();
        set.Bind(CheckBox).For(c => c.On).To(vm => vm.IsCheckBoxOn);
        set.Apply();
    }
}

Это мой класс ViewModel

public class MyViewModel : BaseViewModel
{
    private bool _isCheckBoxOn;
    public bool IsCheckBoxOn
    {
        get => _isCheckBoxOn;
        set
        {
            SetProperty(ref _isCheckBoxOn, value);
            Console.WriteLine(_isCheckBoxOn);
        }
    }

    public MyViewModel : base()
    {
    }

    public override Task Initialize()
    {
        return base.Initialize();
    }
}

Когда я делаю то же самое для UISwitch, он работает отлично. Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 09 мая 2020

MvvmCross включает множество привязок целевых объектов из коробки, UISwitch является одной из них. Полный список см. В разделе « встроенные привязки » в документации MvvmCross.

Односторонняя привязка (ViewModel -> View)

По умолчанию вы можете создать привязку для присвоения значения свойству на ваше представление из вашей модели представления, это называется односторонней привязкой. Этот подход работает даже с настраиваемыми сторонними элементами управления, если типы совпадают.

Двусторонняя привязка ( ViewModel -> View && View -> ViewModel )

Чтобы выполнить двустороннюю привязку, MvvmCross нуждается в механизме представления для уведомления модели представления об изменении значения представления. Для этого MvvmCross использует привязки цели. См. Документацию MvvCross для создания настраиваемых целевых привязок.


Пример

См. Исходный код MvvmCross для MvxUISwitchOnTargetBinding.cs, где показано, как они работают привязка для элемента управления UISwitch и состояния On.

public class MvxUISwitchOnTargetBinding : MvxTargetBinding<UISwitch, bool>
{
    private IDisposable _subscription;

    public MvxUISwitchOnTargetBinding(UISwitch target)
        : base(target)
    {
    }

    protected override void SetValue(bool value)
    {
        Target.SetState(value, true);
    }

    public override void SubscribeToEvents()
    {
        var uiSwitch = Target;
        if (uiSwitch == null)
        {
            MvxBindingLog.Error( "Error - Switch is null in MvxUISwitchOnTargetBinding");
            return;
        }
        _subscription = uiSwitch.WeakSubscribe(nameof(uiSwitch.ValueChanged), HandleValueChanged);
    }

    public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay;

    protected override void Dispose(bool isDisposing)
    {
        base.Dispose(isDisposing);
        if (!isDisposing) return;
        _subscription?.Dispose();
        _subscription = null;
    }

    private void HandleValueChanged(object sender, EventArgs e)
    {
        FireValueChanged(Target.On);
    }
}

Примечание метод HandleValueChanged, который вызывает метод FireValueChanged(), это метод который передает значение, которое вы хотите отправить обратно в вашу связанную модель представления.

Затем вам нужно будет зарегистрировать свои настраиваемые целевые привязки в своем классе Setup.cs, переопределив FillTargetFactories.

...