WPF应用程序的ICommand impation中的CS0201错误 [英] CS0201 error in ICommand impmentation for WPF application
问题描述
我开发了WPF应用程序,很明显,我使用MVVM模式.没有外部库(MvvmCross,MvvmLight等)
我已经尝试实现 ICommand
:
选项1
public class Command:ICommand{私有只读Func< bool>_canExecute;私有只读Action _action;公共Command1(动作,Func< bool> canExecute){_action =动作;_canExecute = canExecute;}公共事件EventHandler CanExecuteChanged{添加{CommandManager.RequerySuggested + =值;}删除{CommandManager.RequerySuggested-=值;}}公共布尔CanExecute(对象参数)=>真的;public void Execute(对象参数)=>_行动();}
选项2
public class Command:ICommand{私有只读Func< bool>_canExecute;私有只读Action< object>_行动;public Command1(Action< object>动作,Func< bool> canExecute){_action =动作;_canExecute = canExecute;}公共事件EventHandler CanExecuteChanged{添加{CommandManager.RequerySuggested + =值;}删除{CommandManager.RequerySuggested-=值;}}公共布尔CanExecute(对象参数)=>真的;public void Execute(对象参数)=>_action(参数);}
选项3
...与一些代表
public class Command:ICommand{私有只读Func< object,bool>_canExecute;私有只读Action< object>_执行;public Command(Action< object> execute)=>_execute =执行抛出新的ArgumentNullException(nameof(execute));公共命令(执行动作):此((Action< object>)委托{execute();}){如果(执行== null){抛出新的ArgumentNullException(nameof(execute));}}公共命令(Action< object>执行,Func< object,bool> canExecute):this(execute)=>_canExecute = canExecute ??抛出新的ArgumentNullException(nameof(canExecute));公共命令(动作执行,Func< bool> canExecute):this(委托{执行();},(对象o)=>canExecute()){如果(执行==空){抛出新的ArgumentNullException(nameof(execute));}如果(canExecute == null){抛出新的ArgumentNullException(nameof(canExecute));}}公共事件EventHandler CanExecuteChanged{添加{CommandManager.RequerySuggested + =值;}删除{CommandManager.RequerySuggested-=值;}}公共布尔CanExecute(对象参数)=>_canExecute!= null吗?_canExecute(parameter):true;public void Execute(对象参数)=>_execute(参数);}
在所有情况下:
公共类MainViewModel:BaseViewModel{公共ICommand MyCommand =新Command(()=> MyVoid());私人void MyVoid(){//做一点事}}
公共类MainViewModel:BaseViewModel{公共ICommand MyCommand =新的Command(MyVoid);私人void MyVoid(){//做一点事}}
我遇到CS0201错误(只能将赋值,调用,递增,递减,等待和新对象表达式用作语句).
我不明白为什么.
在其他使用MVVM模式的项目(Xamarin.Forms,Xamarin等)中,我使用 Xamarin.Forms.Command
或 MvxCommand
(MvvmCross)和它有效...
我不建议将真正的类命名为 Command
,因为您可能会与某些内置类发生命名冲突.>
最接近您的尝试代码的
public ICommand MyCommand =>新的命令(参数=> {MyVoid();});
或与"block"语法相同
公共ICommand MyCommand{得到{返回新的命令(参数=> {MyVoid();});}}
但这是错误的方法,因为每次调用命令时都会创建新的 Command
实例.尽量减少垃圾收集器的工作量.您可以在下面找到正确的操作方法示例.
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();
}
Option 2
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);
}
Option 3
...with some delegates
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);
}
In all cases:
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
}
}
I've a CS0201 error (Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement).
I don't understand why.
In other projects, which use MVVM pattern (Xamarin.Forms, Xamarin, ...), I use Xamarin.Forms.Command
or MvxCommand
(MvvmCross) and it works...
I don't suggest to name the realying class Command
because you may get naming conflict with some built-in classes.
The closest to your try code:
public ICommand MyCommand => new Command(parameter => { MyVoid(); });
or the same in "block" syntax
public ICommand MyCommand
{
get
{
return new Command(parameter => { MyVoid(); });
}
}
But it's wrong approach because it will create new Command
instance each time the command was called. Give to Garbage Collector as less work as possible. Examples of the correct ways doing it you may find below.
You're developing another bicycle. :) Look here.
Here is copy-paste from my project. It's exactly the same as in above link.
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);
}
And the usage
<Button Contecnt="Click me!" Command="{Binding MyCommand}"/>
private ICommand _myCommand;
public ICommand MyCommand => _myCommand ?? (_myCommand = new RelayCommand(parameter =>
{
// do here the execution
}));
And with parameter
(Binding
for CommandParameter
is available too)
<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
}
}));
And finally, usage of optional 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
));
if CanExecute
returns false
, the command will not be executed and Button
or MenuItem
becomes automatically disabled. Just test it.
这篇关于WPF应用程序的ICommand impation中的CS0201错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!