WPF命令 - 绑定不起作用,直接调用。为什么呢?

时间:2015-08-19 08:41:39

标签: c# wpf xaml mvvm

这个问题只是为了理解。只要应用程序有效,我的IDE就可以告诉我那些不存在的错误。

我正在使用MVVM模式开发一个c#WPF应用程序;数据和CommandBindings

但是,我注意到当我使用绑定绑定到Command时,命令不会执行,但是,我没有在IDE或调试输出中显示任何错误

例如:

Command="{Binding MyCommand}"
<!-- Or -->
Command="{Binding cmd:Commands.MyCommand}"

然而,只需写

Command="cmd:Command.MyCommand"

工作得很好,虽然XAML编辑器显示错误,说无法找到命令。

为什么会这样?

2 个答案:

答案 0 :(得分:1)

这是我使用的relayCommand:

  public sealed class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _action;
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion  Fields

    #region Constructors

    public RelayCommand(Action<object> action)
    {
        if (action != null)
            _action = action;
    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion Constructors

    #region ICommand Members

    public void Execute(object parameter)
    {
        if (_execute != null)
            _execute(parameter);
        else
        {
            _action(parameter ?? "Command parameter is null!");
        }
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    #endregion
}

您需要在viewModel命令中实现,您将能够像这样绑定它:

Command="{Binding MyCommand}"

修改 至于我,我更喜欢使用两个库 - 交互和交互。在他们的帮助下,很容易将所有事件绑定到viewModel。例如:

XAML:

<i:Interaction.Triggers>
     <i:EventTrigger EventName="Click">
           <ei:CallMethodAction TargetObject="{Binding}" MethodName="OnClick"/>
     </i:EventTrigger>                
</i:Interaction.Triggers>

和viewModel:

public void OnClick(object sender, RoutedEventArgs e)
{
    //your code
}

答案 1 :(得分:1)

您需要绑定到ICommand类型的属性。 此属性将使用您的函数实现RelayCommand

RelayCommand的默认实现如下:

public class RelayCommand : ICommand
{
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    private readonly Action methodToExecute;
    private readonly Func<bool> canExecuteEvaluator;
    public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
    {
        this.methodToExecute = methodToExecute;
        this.canExecuteEvaluator = canExecuteEvaluator;
    }
    public RelayCommand(Action methodToExecute)
        : this(methodToExecute, null)
    {
    }
    public bool CanExecute(object parameter)
    {
        if (canExecuteEvaluator == null)
        {
            return true;
        }
        bool result = canExecuteEvaluator.Invoke();
        return result;
    }
    public void Execute(object parameter)
    {
        methodToExecute.Invoke();
    }
}

在ViewModel中,您需要使用OnClick函数实现类型ICommand的属性:

public ICommand MyCommand
{
    get
    {
        return new RelayCommand(() =>
        {
            doSomething();
        });
    }
}

现在,您可以在运行时动态地将视图的Button-Command绑定到ICommand:

Command="{Binding MyCommand}"

此外,请记住Command="cmd:Command.MyCommand"是静态实现。