使用 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);
}
}
}
我有一个用于 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);
}
}
}