当我将CommandParameter设置为某个Binding时,为什么我的ICommand.CanExecute(object)参数为null,但当我将其设置为某个静态值时为非null?

时间:2014-09-29 14:20:08

标签: c# wpf icommand

我正在学习WPF中的ICommands,我遇到了一些简单代码的问题。我有一个带命令的按钮。如果我将command参数设置为这样的静态值CommandParameter="100",则CanExecute中parameter参数的值为100,但是当我通过绑定设置命令参数的值时,这样CommandParameter="{Binding}" 1}},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代码。请注意,我在设置Command之前设置了CommandParameter。我得到了from here。同样,如果我将CommandParameter更改为类似CommandParameter="100"的内容,代码就像我期望的那样(即参数为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课很简单,所以我把它留了出来。

2 个答案:

答案 0 :(得分:3)

这也是一种解决办法,通过提高命令的CanExecute事件,强制从Loaded事件的FrameworkElement重新评估CanExecuteChanged。当您使用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}

答案 1 :(得分:1)

CanExecuteChanged完成后尝试提升MyCommand - InitializeComponent()类的事件。可能在第一次渲染时调用CanExecute(object) MyCommand来初始化按钮的状态,而绑定尚未完全初始化。