使用 mvvmcross 以与 Click 事件相同的方式触发 switch Checked 事件

Getting a switch Checked event to fire in the same way as a Click event with mvvmcross

我有一个用于 Android 的 mvvmcross 项目正在开发中,并且最近更改了 UI 的一部分以使用开关而不是按钮来从愿望清单中删除项目。默认情况下,开关设置为开。在按钮版本中,当按下按钮时,项目立即被删除。

按钮是使用 Click RemoveCommand 绑定的,而开关是使用设计器中的 Checked RemoveCommand 绑定的。

按钮工作正常并删除了项目,但开关抛出绑定警告,指出目标 属性 是只读的。我想做的是当开关改变时,以与单击按钮相同的方式从愿望列表中删除该项目。

有没有办法让选中的事件以与单击事件相同的方式运行?

最简单的答案:

  • 我认为 Checked 是布尔值 属性 的绑定 - 因此您可以将视图上的 Checked 绑定到 ViewModel 上的布尔值(并且如果需要,然后在 set 处理程序中处理一些逻辑。

  • 或者,如果您想要一个简单的无参数 Command 绑定,那么您可以只使用 Click


如果您想进行 Command<bool> 绑定,那么您可以使用 https://github.com/MvvmCross/MvvmCross/blob/c306ba37afd9024f68b7a4f1fedcaf4cf7d01b8d/Cirrious/Cirrious.MvvmCross.Binding.Droid/Target/MvxCompoundButtonCheckedTargetBinding.cs and https://github.com/MvvmCross/MvvmCross/blob/c306ba37afd9024f68b7a4f1fedcaf4cf7d01b8d/Cirrious/Cirrious.MvvmCross.Binding.Droid/Target/MvxViewClickBinding.cs 中的代码作为模板快速创建一个 - 类似于:

    using System.Reflection;
    using Android.Widget;
    using Cirrious.CrossCore.Platform;
    using Cirrious.MvvmCross.Binding.Bindings.Target;

    namespace MyApp.Ext.Target
    {
        public class MyCompoundButtonCheckedTargetBinding
            : MvxAndroidTargetBinding
        {
            private ICommand _command;
            private IDisposable _canExecuteSubscription;
            private readonly EventHandler<EventArgs> _canExecuteEventHandler;

            protected CompoundButton View
            {
                get { return (CompoundButton)Target; }
            }

            public MyCompoundButtonCheckedTargetBinding(View view)
                : base(target, targetPropertyInfo)
            {
                _canExecuteEventHandler = new EventHandler<EventArgs>(OnCanExecuteChanged);
                SubscribeToEvents();
            }

            public override MvxBindingMode DefaultMode
            {
                get { return MvxBindingMode.OneWay; }
            }

            public override Type TargetType
            {
                get { return typeof(ICommand); }
            }

            public override void SubscribeToEvents()
            {
                var compoundButton = View;
                if (compoundButton == null)
                {
                    MvxBindingTrace.Trace(MvxTraceLevel.Error,
                                          "Error - compoundButton is null in MvxCompoundButtonCheckedTargetBinding");
                    return;
                }

                _subscribed = true;
                compoundButton.CheckedChange += CompoundButtonOnCheckedChange;
            }

            private void RefreshEnabledState()
            {
                var view = View;
                if (view == null)
                    return;

                var value = view.Checked;

                var shouldBeEnabled = false;
                if (_command != null)
                {
                    shouldBeEnabled = _command.CanExecute(value);
                }
                view.Enabled = shouldBeEnabled;
            }

            private void OnCanExecuteChanged(object sender, EventArgs e)
            {
                RefreshEnabledState();
            }

            protected override void SetValueImpl(object target, object value)
            {
                if (_canExecuteSubscription != null)
                {
                    _canExecuteSubscription.Dispose();
                    _canExecuteSubscription = null;
                }
                _command = value as ICommand;
                if (_command != null)
                {
                    _canExecuteSubscription = _command.WeakSubscribe(_canExecuteEventHandler);
                }
                RefreshEnabledState();
            }

            private void CompoundButtonOnCheckedChange(object sender, CompoundButton.CheckedChangeEventArgs args)
            {
                if (_command == null)
                    return;

                var value = args.IsChecked; /* TODO - check this name... */

                if (!_command.CanExecute(value))
                    return;

                _command.Execute(value);
            }

            protected override void Dispose(bool isDisposing)
            {
                if (isDisposing)
                {
                    var view = View;
                    if (view != null)
                    {
                        view.CheckedChange -= CompoundButtonOnCheckedChange;
                    }
                    if (_canExecuteSubscription != null)
                    {
                        _canExecuteSubscription.Dispose();
                        _canExecuteSubscription = null;
                    }                
                }
                base.Dispose(isDisposing);
            }
        }
    }