我无法让我的命令的 CanExecute 方法工作属性。我已将命令绑定到 DataGrid 内的按钮。我已将 CommandParameter 绑定到按钮的 DataContext,它恰好是 DataGrid 中一行的记录。
我期望发生的是在 CommandParameter 绑定更改时重新评估 CanExecute 方法,在这种情况下,这将是设置行的 DataContext 属性。但是,不是针对行数据评估 CanExecute 方法,而是在行获取其 DataContext 之前评估 CanExecute 方法,并且在更新 DataContext 之后永远不会重新评估它。
你能告诉我如何让我的命令的 CanExecute 方法针对每一行的 DataContext 进行评估吗?
我创建了一个示例应用程序来演示我的问题。这是代码:
MainWindow.xaml 的代码隐藏
public partial class MainWindow : Window
{
public ObservableCollection<LogRecord> Records { get; private set; }
public ICommand SignOutCommand { get; private set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Records = new ObservableCollection<LogRecord>();
SignOutCommand = new SignOutCommand();
CreateDemoData();
}
private void CreateDemoData()
{
for (int i = 0; i < 5; i++)
{
Records.Add(new LogRecord());
}
}
}
public class LogRecord : INotifyPropertyChanged
{
private DateTime _EntryTime;
public DateTime EntryTime
{
get { return _EntryTime; }
set
{
if (_EntryTime == value) return;
_EntryTime = value;
RaisePropertyChanged("EntryTime");
}
}
private DateTime? _ExitTime;
public DateTime? ExitTime
{
get { return _ExitTime; }
set
{
if (_ExitTime == value) return;
_ExitTime = value;
RaisePropertyChanged("ExitTime");
}
}
public LogRecord()
{
EntryTime = DateTime.Now;
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class SignOutCommand : ICommand
{
#region Implementation of ICommand
public void Execute(object parameter)
{
var record = parameter as LogRecord;
if (record == null) return;
record.ExitTime = DateTime.Now;
}
public bool CanExecute(object parameter)
{
var record = parameter as LogRecord;
return record != null && !record.ExitTime.HasValue;
}
public event EventHandler CanExecuteChanged;
#endregion
}
MainWindow.xaml 的 XAML
<Window x:Class="Command_Spike.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<DataGrid ItemsSource="{Binding Path=Records}" IsReadOnly="True" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Entry Time" Binding="{Binding Path=EntryTime}" />
<DataGridTextColumn Header="Exit Time" Binding="{Binding Path=ExitTime}" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Window},
Path=DataContext.SignOutCommand}"
CommandParameter="{Binding}"
Content="Sign Out" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
如果加载示例代码,您会看到所有的“退出”按钮都被禁用,因为在每一行中,CanExecute 方法都接收 null 作为参数,而不是我想要的特定于行的数据。如果此示例工作正常,所有按钮最初都会启用,并且只有在设置了 Exit Time 列中的值后才会禁用。