WPF应用程序的ICommand impation中的CS0201错误 [英] CS0201 error in ICommand impmentation for WPF application

查看:80
本文介绍了WPF应用程序的ICommand impation中的CS0201错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了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 实例.尽量减少垃圾收集器的工作量.您可以在下面找到正确的操作方法示例.

您正在开发另一辆自行车.:)看起来 公共类RelayCommand:ICommand{私有只读Action< object>_执行;私有只读Func< object,bool>_canExecute;公共事件EventHandler CanExecuteChanged{添加{CommandManager.RequerySuggested + =值;}删除{CommandManager.RequerySuggested-=值;}}公共RelayCommand(Action< object>执行,Func< object,bool> canExecute = null){_execute =执行;_canExecute = canExecute;}公共布尔CanExecute(对象参数)=>_canExecute == null ||_canExecute(参数);public void Execute(对象参数)=>_execute(参数);}

以及用法

 < Button Contecnt =点击我!"Command ="{Binding MyCommand}"/> 

 私有ICommand _myCommand;公共ICommand MyCommand =>_myCommand ??(_myCommand =新的RelayCommand(参数=>{//在这里执行})); 

并且具有 parameter ( CommandParameter Binding 也可用)

 < Button Contecnt =点击我!"Command ="{Binding MyCommand}" CommandParameter =测试值"/> 

  public ICommand MyCommand =>_myCommand ??(_myCommand =新的RelayCommand(参数=>{if(参数是字符串p&& p ==测试值"){//在这里执行}})); 

最后,使用可选的 CanExecute

  public ICommand MyCommand =>_myCommand ??(_myCommand =新的RelayCommand(参数=>{//在这里执行//不要在此处输入与CanExecute中相同的条件,//在执行进入此块之前已经检查过},参数=>(x> y)&&(a + b> c)//任何条件或仅返回布尔值)); 

如果 CanExecute 返回 false ,该命令将不会执行,并且 Button MenuItem 将自动被禁用.只是测试一下.

I develop a WPF application, obviously, I use MVVM pattern. Without an external library (MvvmCross, MvvmLight, ...)

And I've tried to implement ICommand:

Option 1

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆