繁体   English   中英

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

[英]Why is my ICommand.CanExecute(object) parameter null when I set CommandParameter to some Binding, but non-null when I set it to some static value?

我正在学习WPF中的ICommands,我遇到了一些简单代码的问题。 我有一个带命令的按钮。 如果我将command参数设置为这样的静态值, 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代码。 请注意,我在设置Command之前设置了CommandParameter。 从这里得到了。 同样,如果我将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类非常简单,所以我把它留了下来。

它也是一种解决方案,通过引发命令的CanExecuteChanged事件, CanExecuteLoadedFrameworkElement事件中重新评估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 -event。 可能会调用MyCommandCanExecute(object)来在第一次渲染时初始化按钮的状态,而绑定尚未初始化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM