2012-10-23 34 views
1

我试图在自定义控件上实现ICommandSource(类似于按钮)。目前这个实现大部分就像在ICommandSource的msdn页面上显示的一样,并且在ButtonBase源代码中显示。在属性更改上重新评估CanExecute

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

我试过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} 
+0

什么属性更改? – user195275

+0

其INotifyChangedProperty – Bambu

回答

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

随着delegate命令,你必须提高CanExecuteChanged明确,只要你认为它应该在UI上更新。尝试使用这个版本的命令叫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 
} 

而在你的讲座

public ICommand TestCommand { get; private set; } 
TestCommand = new RelayCommand<object>(CommandMethod, CanExecuteCommand); 

编辑这样注册Delegate命令

尝试把CommandManager.InvalidateRequerySuggested();CanExecute -

private void OnCanExecuteChanged(object sender, EventArgs e) 
{ 
    CommandManager.InvalidateRequerySuggested(); 
    UpdateCanExecute(); 
} 
+0

我的DelegateCommand大致是完全相同的代码。只是在这里和那里的一些差异。但是,不,这也行不通。 – Bambu

+0

现在你可以尝试编辑的答案吗? –

+0

没有。仍然不起作用。常规按钮仍然正常工作,但是,自定义控件没有。当我修改需要更改的属性时,自定义控件上的OnCanExecuteChanged不会触发。在自定义控件OnCanExecuteChanged仅在该视图模型被加载/重载时触发。 – Bambu