在房产变更时重新评估CanExecute

时间:2012-10-23 18:53:55

标签: c# wpf icommand

我正在尝试在自定义控件上实现ICommandSource(类似于按钮)。目前,实现主要类似于它显示在msom页面上的ICommandSource,并且显示在ButtonBase源代码中。

CanExecute在控件加载时触发,但在任何属性发生更改时不会触发。传递给常规按钮的相同命令工作得很好。当应该更改的属性发生更改时,CanExecute将触发并启用该按钮。该命令是Delegate Command。

我尝试过CommandManager.InvalidateRequerySuggested();但这没效果。

有什么想法吗?

以下是自定义控件中的实现:

private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    CollapsibleSplitButton csb = (CollapsibleSplitButton)d;
    csb.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
}

private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
{
    if (oldCommand != null) UnhookCommand(oldCommand);
    if (newCommand != null) HookCommand(newCommand);
}

private void UnhookCommand(ICommand command)
{
    command.CanExecuteChanged -= OnCanExecuteChanged;
    UpdateCanExecute();
}

private void HookCommand(ICommand command)
{
    command.CanExecuteChanged += OnCanExecuteChanged;
    UpdateCanExecute();
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
    UpdateCanExecute();
}

private void UpdateCanExecute()
{
    if (Command != null)
        CanExecute = Command.CanExecute(CommandParameter);
    else
        CanExecute = true;
}

protected override bool IsEnabledCore
{
    get { return base.IsEnabledCore && CanExecute; }
}

我在哪里设置命令:

...
    MyCommand = new DelegatingCommand(DoStuff, CanDoStuff);
...

private bool CanDoStuff()
{
    return (DueDate == null);
}

private void DoStuff() {//do stuff}

2 个答案:

答案 0 :(得分:1)

使用delegate命令,只要您认为应在UI上更新CanExecuteChanged,就必须明确提升RelayCommand。尝试使用此版本的命令public class RelayCommand<T> : ICommand { #region Fields readonly Action<T> _execute = null; readonly Predicate<T> _canExecute = null; #endregion #region Constructors /// <summary> /// Initializes a new instance of <see cref="DelegateCommand{T}"/>. /// </summary> /// <param name="execute">Delegate to execute when Execute is called on the command. ///This can be null to just hook up a CanExecute delegate.</param> /// <remarks><seealso cref="CanExecute"/> will always return true.</remarks> public RelayCommand(Action<T> execute) : this(execute, null) { } /// <summary> /// Creates a new command. /// </summary> /// <param name="execute">The execution logic.</param> /// <param name="canExecute">The execution status logic.</param> public RelayCommand(Action<T> execute, Predicate<T> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion #region ICommand Members ///<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 bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute((T)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; } } ///<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 <see langword="null" />.</param> public void Execute(object parameter) { _execute((T)parameter); } #endregion } -

Delegate

在您的班级中注册public ICommand TestCommand { get; private set; } TestCommand = new RelayCommand<object>(CommandMethod, CanExecuteCommand); 命令 -

CommandManager.InvalidateRequerySuggested();

修改

尝试将CanExecute放入private void OnCanExecuteChanged(object sender, EventArgs e) { CommandManager.InvalidateRequerySuggested(); UpdateCanExecute(); } -

{{1}}

答案 1 :(得分:0)

通过将回调包装在EventHandler中来管理解决问题。

private EventHandler currentHandler;

private void UnhookCommand(ICommand command)
{
    if (currentHandler != null)
        command.CanExecuteChanged -= currentHandler;
    UpdateCanExecute();
}

private void HookCommand(ICommand command)
{
    if (currentHandler == null) return;

    command.CanExecuteChanged += currentHandler;
    UpdateCanExecute();
}