WPF Button CommandParameter未正确传递给Command

时间:2015-11-29 13:38:28

标签: c# wpf mvvm catel

我将CommandParameter传递给我的命令

时遇到问题

我有命令:

private Command<Boolean> _setAsCompletedCommand;
public Command<Boolean> SetAsCompletedCommand
{
    get
    {
        return _setAsCompletedCommand ?? (_setAsCompletedCommand = new Command<Boolean>(isToComplete =>
        {
            if (isToComplete)
            {
                //do something
            }
            else
            {
                //do something else
            }
        }, isToComplete =>
        {
            if (isToComplete)
            {
                //check something
            }
            else
            {
                //check something else
            }

        }));
    }
}

我尝试传递system:Boolean,如下所示:

<Button
    Command="{Binding SetAsCompletedCommand}">
    <Button.CommandParameter>
        <system:Boolean>
            True
        </system:Boolean>
    </Button.CommandParameter>
</Button>

问题是,在构建视图时,我的SetAsCompletedCommand.CanExecute()是使用False参数执行的。

怎么可能?我该如何解决?

当我点击按钮时,CommandParameter已正确设置为True

我在这个项目中使用Catel框架作为MVVM框架。但我认为它不会产生问题。

2 个答案:

答案 0 :(得分:0)

首先,我不会以这种方式创建属性。你应该坚持使用简单的属性,让命令本身完成所有的工作。我建议编写一个自定义命令,让它继承自这样的命令基类:

using System;
using System.Windows.Input;

namespace MyCommands
{
    /// <summary>
    /// Base class for all Commands.
    /// </summary>
    public abstract class CommandBase : ICommand
    {
        /// <summary>
        /// Defines the method that determines whether the command can execute in its current 
        /// state.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data 
        /// to be passed, this object can be set to null.</param>
        /// <returns>
        /// true if this command can be executed; otherwise, false.
        /// </returns>
        public virtual bool CanExecute(object parameter) 
        {
            return true;
        }

        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data 
        /// to be passed, this object can be set to null.</param>
        public virtual void Execute(object parameter) {}

        /// <summary>
        /// Occurs when changes occur that affect whether or not the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
}

在那里,您可以通过分别覆盖 CanExecute 执行来指定允许命令执行的条件以及执行命令时应执行的操作。

答案 1 :(得分:0)

这非常棘手,是由绑定执行的顺序引起的。一旦绑定更新,WPF就会在您的命令上运行CanExecute。 在此阶段 CommandParameter尚未绑定,Catel使用布尔值(.htaccess)的默认值作为命令参数。

之后,只有在属性更改时才会重新评估命令。例如,除非属性更改,否则Catel没有理由使状态的命令无效。

解决此问题的一个解决方案是在视图模型的false中使用CommandManager.InvalidateCommands(true)。这将使vm上的所有命令的状态无效并重新评估它们(在此阶段,命令参数的绑定是正确的。)

您可能会问自己:“为什么不在初始化方法中自动重新评估?”。

嗯,我们过去做过,但我们希望提供更好的开箱即用性能。这可能是您第一次使用命中参数来达到此限制,但我认为您过去创建了更多命令。这意味着到目前为止你在所有其他命令上都有性能改进,所以我仍然认为这是一个很好的决定。还有足够的解决方法来恢复旧的行为,它使用InitializeAsync的WPF来重新评估几乎每个路由事件(鼠标移动,键盘等)上的命令。