我正在学习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
课很简单,所以我把它留了出来。
答案 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
来初始化按钮的状态,而绑定尚未完全初始化。