在WPF中,能否使用Command.CanExecute设置工具提示?

在WPF中,能否使用Command.CanExecute设置工具提示?,wpf,command,Wpf,Command,我知道这不是真正的代码。但这正是我想做的 MyBinding.CanExecute += (s, e) => { e.CanExecute = Something.Allow; if (!e.CanExecute) e.ToolTip = Something.Reason; } 有简单的方法吗 谢谢。根据您的问题,我假设您是从ViewModel执行此操作的。如果是这样,最简单的方法就是为命令提供一个可观察的CanExecute属性,为工具提示提供另一个s

我知道这不是真正的代码。但这正是我想做的

MyBinding.CanExecute += (s, e) => 
{
    e.CanExecute = Something.Allow;
    if (!e.CanExecute)
        e.ToolTip = Something.Reason;
}
有简单的方法吗


谢谢。

根据您的问题,我假设您是从ViewModel执行此操作的。如果是这样,最简单的方法就是为命令提供一个可观察的CanExecute属性,为工具提示提供另一个string Reason属性

然后,在ViewModel中侦听PropertyChanged事件。当CanExecute属性更改时,只需更新原因

下面是一些示例代码,它在执行命令时将CanExecute属性设置为false:

public MyViewModel()
    : base()
{
    this.PropertyChanged += (s, e) =>
        {
            if (e.PropertyName == "SomeCommandCanExecute")
            {
                if (mSomeCommandCanExecute)
                    this.Reason = "Some Command Can Execute";
                else
                    this.Reason = "Some Command Cannot Execute Because....";
            }
        };
}

private RelayCommand mSomeCommand = null;
private Boolean mSomeCommandCanExecute = true;
public RelayCommand SomeCommand
{
    get
    {
        if (mSomeCommand == null)
        {
            mSomeCommand = new RelayCommand(
                cmd => this.ExecuteSomeCommand(),
                cmd => this.SomeCommandCanExecute);
        }

        return mSomeCommand;
    }
}

public Boolean SomeCommandCanExecute
{
    get { return mSomeCommandCanExecute; }
    set { SetProperty("SomeCommandCanExecute", ref mSomeCommandCanExecute, value); }
}


private void ExecuteSomeCommand()
{
    this.SomeCommandCanExecute = false;
}

private string mReason = "Some Command Can Execute";
public string Reason
{
    get { return mReason; }
    set { SetProperty("Reason", ref mReason, value); }
}
在你看来:

   <StackPanel>
        <Button Command="{Binding SomeCommand}"
                ToolTip="{Binding Reason}"
                Content="Some Command"/>
        <TextBlock Text="{Binding Reason}"
                   ToolTip="{Binding Reason}" />
   </StackPanel>

请注意,当CanExecute设置为false时,您将看不到禁用按钮上的工具提示,这就是我添加TextBlock来显示它的原因。您将在文本块上看到工具提示。

我认为这是实现此目的的最佳方法

这是命令定义:

class CustomCommand : RoutedUICommand, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string m_Reason;
    public string Reason
    {
        get { return m_Reason; }
        set
        {
            if (m_Reason == value)
                return;
            m_Reason = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Reason"));
        }
    }
}
public class MyCommands
{
    public static CustomCommand DoThis = new CustomCommand();
    public static CommandBinding DoThisBinding = new CommandBinding 
        { Command = DoThis };

    public static void SetupCommands()
    {
        DoThisBinding.CanExecute += (s, e) =>
        {
            var _Something = DoSomeTest(e.Parameter);
            e.CanExecute = _Something.Allow;     
            if (!e.CanExecute)         
                (e.Command as CustomCommand).Reason = _Something.Reason; 
        } 
    }
}
这是XAML实现:

xmlns:commands="MyNamespace.WhereAreCommands"

<Button Command="{x:Static commands:MyCommands.DoThis}"
        ToolTip="{Binding Path=Reason, 
            Source={x:Static commands:MyCommands.DoThis}}">
    Click</Button>

是否缺少TextBlock到按钮的DataContext绑定?否。这是一个MVVM实现,它假定整个视图的DataContext绑定到ViewModel的一个实例。SomeCommand和Reason都是绑定视图模型的属性。在本例中,按钮和TextBlock是独立控件-此处显示的TextBlock可以是文本框、按钮或____;它仅用于显示绑定属性,尤其是因为您无法看到禁用按钮上的工具提示。不,很抱歉,我不同意您的意见,但是您的实现会导致每个命令都有相同的原因。对不起,从您的问题来看,我没有意识到您想要有多个原因。即使如此,您也可以轻松地使用CommandParameter为同一命令的多次出现设置适当的原因;如果不同的CanExecute处理程序/方法将工具提示设置为不同的值,您将获得非常不稳定的行为;使用ViewModel,您可以更好地控制何时以及如何设置工具提示这是一个很好的观点。CANEx执行的条件很可能被设置为将某个事件或方法中间的原因设置为另一种方式的副产品。