WPF应用程序的ICommand实施中的CS0201错误

问题描述 投票:0回答:1

我开发了WPF应用程序,显然,我使用MVVM模式。没有外部库(MvvmCross,MvvmLight等)

而且我尝试实现ICommand

选项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();
}

选项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);
}

选项3

...与一些代表

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.CommandMvxCommand(MvvmCross),并且有效...

c# wpf mvvm binding command
1个回答
0
投票

我不建议将实际类命名为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
}));

并且使用parameterBindingCommandParameter也可用)

<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,将不会执行该命令,并且ButtonMenuItem将自动被禁用。只是测试一下。

© www.soinside.com 2019 - 2024. All rights reserved.