我开发了WPF应用程序,显然,我使用MVVM模式。没有外部库(MvvmCross,MvvmLight等)
而且我尝试实现ICommand
:
public class Command : ICommand
{
private readonly Func<bool> _canExecute;
private readonly Action _action;
public Command1(Action action, Func<bool> canExecute)
{
_action = action;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _action();
}
public class Command : ICommand
{
private readonly Func<bool> _canExecute;
private readonly Action<object> _action;
public Command1(Action<object> action, Func<bool> canExecute)
{
_action = action;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _action(parameter);
}
...与一些代表
public class Command : ICommand
{
private readonly Func<object, bool> _canExecute;
private readonly Action<object> _execute;
public Command(Action<object> execute) => _execute = execute ?? throw new ArgumentNullException(nameof(execute));
public Command(Action execute)
: this((Action<object>)delegate { execute(); })
{
if (execute == null)
{
throw new ArgumentNullException(nameof(execute));
}
}
public Command(Action<object> execute, Func<object, bool> canExecute)
: this(execute) => _canExecute = canExecute ?? throw new ArgumentNullException(nameof(canExecute));
public Command(Action execute, Func<bool> canExecute)
: this(delegate
{
execute();
}, (object o) => canExecute())
{
if (execute == null)
{
throw new ArgumentNullException(nameof(execute));
}
if (canExecute == null)
{
throw new ArgumentNullException(nameof(canExecute));
}
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter) => _canExecute != null ? _canExecute(parameter) : true;
public void Execute(object parameter) => _execute(parameter);
}
在所有情况下:
public class MainViewModel : BaseViewModel
{
public ICommand MyCommand = new Command(() => MyVoid());
private void MyVoid()
{
// do something
}
}
public class MainViewModel : BaseViewModel
{
public ICommand MyCommand = new Command(MyVoid);
private void MyVoid()
{
// do something
}
}
我遇到CS0201错误(仅赋值,调用,递增,递减,等待和新的对象表达式可以用作语句)。
我不明白为什么。
[在其他使用MVVM模式的项目中(Xamarin.Forms,Xamarin ...),我使用Xamarin.Forms.Command
或MvxCommand
(MvvmCross),并且有效...
我不建议将实际类命名为Command
,因为您可能会与某些内置类发生命名冲突。
最接近您的尝试代码:
public ICommand MyCommand => new Command(parameter => { MyVoid(); });
或“ block”语法相同
public ICommand MyCommand
{
get
{
return new Command(parameter => { MyVoid(); });
}
}
但是这是错误的方法,因为每次调用命令时,它将创建新的Command
实例。尽量减少垃圾收集器的工作。您可以在下面找到正确方法的示例。
您正在开发另一辆自行车。 :)看here。
这里是我的项目中的复制粘贴。与上面的链接完全相同。
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
}
和用法
<Button Contecnt="Click me!" Command="{Binding MyCommand}"/>
private ICommand _myCommand;
public ICommand MyCommand => _myCommand ?? (_myCommand = new RelayCommand(parameter =>
{
// do here the execution
}));
并且使用parameter
(Binding
的CommandParameter
也可用)
<Button Contecnt="Click me!" Command="{Binding MyCommand}" CommandParameter="test value"/>
public ICommand MyCommand => _myCommand ?? (_myCommand = new RelayCommand(parameter =>
{
if (parameter is string p && p == "test value")
{
// do here the execution
}
}));
最后使用可选的CanExecute
public ICommand MyCommand => _myCommand ?? (_myCommand = new RelayCommand(parameter =>
{
// do here the execution
// don't put the same condition as in CanExecute here,
// it was already checked before execution has entered this block
},
parameter => (x > y) && (a + b > c) // any condition or just return a bool
));
如果CanExecute
返回false
,将不会执行该命令,并且Button
或MenuItem
将自动被禁用。只是测试一下。