嗯,通常在 WPF 中人们使用 CommandManager.RequerySuggested 事件和 CommandManager.InvalidateRequerySuggested 方法,当他们想要强制某些控件刷新它的命令 CanExecuted 时。但是我不喜欢并且从不这样做,因为它的效率非常低(所以我不会对此进行详细说明)。所以,我认为最好的方法是:
public class DelegateCommand : ICommand {
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public DelegateCommand(Action<object> execute, Predicate<object> canExecute) {
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) {
return _canExecute(parameter);
}
public void Execute(object parameter) {
_execute(parameter);
}
public void RefreshCanExecute() {
var handler = CanExecuteChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
public event EventHandler CanExecuteChanged;
}
然后当事情发生变化时,只需调用 DelegateCommand.RefreshCanExecute:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
this.BtnCommand = new DelegateCommand(_ => {
MessageBox.Show("test");
}, _ => CheckCanExecute());
this.DataContext = this;
}
private bool CheckCanExecute() {
return SomeProperty == 1;
}
public int SomeProperty
{
get { return (int) GetValue(SomePropertyProperty); }
set { SetValue(SomePropertyProperty, value); }
}
public static readonly DependencyProperty SomePropertyProperty =
DependencyProperty.Register("SomeProperty", typeof(int), typeof(MainWindow), new PropertyMetadata(0, OnSomePropertyChanged));
private static void OnSomePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
((MainWindow) d).BtnCommand.RefreshCanExecute();
}
public DelegateCommand BtnCommand { get; private set; }
}
Xaml:
<Button Content="test" Command="{Binding BtnCommand}" />
编辑以回复评论。当然你可以绑定到多个属性,它只是与命令无关,所以我没有意识到你对此感兴趣。你可以这样做——首先创建多值转换器:
public class AndConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
if (values.Length == 0) return false;
return values.All(c => c != null && c != DependencyProperty.UnsetValue && (bool) c);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
它接受多个布尔值(空值被视为假)并评估它们。现在在 xaml 中,只需将按钮的 IsEnabled 绑定到您的模型属性:
<Window.Resources>
<wpf:AndConverter x:Key="and" />
</Window.Resources>
<Button Content="test" Command="{Binding BtnCommand}">
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource and}">
<Binding Path="IsFirstPage" />
<Binding Path="CanGoToPrevious" />
</MultiBinding>
</Button.IsEnabled>
</Button>
现在在任何绑定属性更改时,您的转换器将被重新评估并刷新按钮的 IsEnabled 属性。