为什么当我将CommandParameter设置为某个Binding时,我的ICommand.CanExecute(ob

本文关键字:我的 ICommand CanExecute ob Binding CommandParameter 设置 为什么 | 更新日期: 2023-09-27 18:25:01

我在WPF中学习ICommands,遇到了一些简单代码的问题。我有一个带命令的按钮。如果我将命令参数设置为像这样的静态值CommandParameter="100",则CanExecute中parameter参数的值为100,但是,当我通过像这样的绑定CommandParameter="{Binding}"设置命令参数的值时,CanExecute的parameter参数的值是null。

这是我的ICommand:

internal class MyCommand : ICommand
{
    public bool CanExecute(object parameter) //parameter is null
    {
        var datacontext = parameter as MyDataContext;
        if (datacontext == null)
            return false;
        return datacontext.IsChecked == true;
    }
    public event EventHandler CanExecuteChanged;
    public void Execute(object parameter)
    {
        throw new NotImplementedException();
    }
}

这是XAML代码。请注意,在设置命令之前,我正在设置CommandParameter。我从这里得到的。同样,如果我将CommandParameter更改为类似CommandParameter="100"的somwthing,代码将按照我的预期运行(即,参数为100,而不是null)。

<StackPanel Orientation="Vertical">
    <StackPanel.Resources>
        <cmd:MyCommand x:Key="kCmd" />
    </StackPanel.Resources>
    <CheckBox Content="Check this to enable button" IsChecked="{Binding IsChecked}" />
    <Button Content="Click" CommandParameter="{Binding}" 
            Command="{StaticResource kCmd}" />
</StackPanel>

这是我的MainWindow代码。在这里,我在调用InitializeComponent()之前设置DataContext。在调试过程中,我发现InitializeComponent()触发了对ICommand的CanExecute(object)的调用。

public MainWindow()
{
    this.DataContext = new MyDataContext();
    InitializeComponent();
}

我的MyDataContext类非常简单,所以我把它省略了。

为什么当我将CommandParameter设置为某个Binding时,我的ICommand.CanExecute(ob

它也是通过引发命令的CanExecuteChanged事件来强制从FrameworkElement事件的开启Loaded重新评估CanExecute的解决方案。当您使用DataTemplate,并且遇到此问题时,尤其可以使用此方法。

示例:

 <DataTemplate x:Key="MyTemplate">
            <Grid Loaded="HandleLoaded">
 ...

背后的代码:

 void HandleLoaded(object sender, RoutedEventArgs e)
 {
     var viewModel = this.DataContext as ViewModel;
     if (viewModel != null)
     {
         viewModel.DoItCommand.RaiseCanExecuteChanged();
     }
 }

另一种可行的解决方案是将与命令本身的绑定定义为IsAsync=True。但这会导致一些闪烁。所以这可能不是最好的选择。

示例:{Binding DoItCommand, IsAsync=True}

InitializeComponent()完成后,尝试引发MyCommand类的CanExecuteChanged-事件。可能,MyCommandCanExecute(object)在第一次呈现时被调用以初始化按钮的状态,而绑定尚未全部初始化。