与 "CanXXXX" 一起监听多个属性
Have a commande with the "CanXXXX" listening to multiple properties
我正在做一个可以显示向导(使用 WPF+Prism)的 UserControl
。
为此,我有两个控件:Wizard
和 WizardPage
。
我希望我能以这样的事情结束
<Wizard>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}">
<TextBlock>Page one</TextBlock>
</WizardPage>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}" CanGoToPrevious="False">
<TextBlock>Page Four</TextBlock>
</WizardPage>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}" CanGoToPrevious="True">
<TextBlock>Page Three</TextBlock>
</WizardPage>
</Wizard>
我目前卡在向导用户控件中的命令上。
我要3个Buttons
:
- 上一个
- 下一个
- 取消
我想在上面绑定 UserControl 的一些命令。
问题是如果按钮的命令可以执行则更新条件。
就我而言,我想:
//PseudoCode
CurrentPage != FirstPage
&& CurrentPage.CanGoToPrevious
但我不知道如何制作 DelegateCommand
并要求他们在 CurrentPage.CanGoToPrevious
的依赖性 属性 发生变化时再次检查其状况?
嗯,通常在 WPF 中,当人们想要强制某些控件刷新其命令 CanExecuted 时,他们使用 CommandManager.RequerySuggested 事件和 CommandManager.InvalidateRequerySuggested 方法。但是我不喜欢那样,也从不那样做,因为它非常低效(所以我不会详细介绍)。所以,我认为最好的方法是:
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();
}
}
它接受多个布尔值(null 被视为 false)并对它们进行求值。现在 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 属性。
我正在做一个可以显示向导(使用 WPF+Prism)的 UserControl
。
为此,我有两个控件:Wizard
和 WizardPage
。
我希望我能以这样的事情结束
<Wizard>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}">
<TextBlock>Page one</TextBlock>
</WizardPage>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}" CanGoToPrevious="False">
<TextBlock>Page Four</TextBlock>
</WizardPage>
<WizardPage CanGoToNext="{Binding SomePropertySayingThatThisPaneIsOk}" CanGoToPrevious="True">
<TextBlock>Page Three</TextBlock>
</WizardPage>
</Wizard>
我目前卡在向导用户控件中的命令上。
我要3个Buttons
:
- 上一个
- 下一个
- 取消
我想在上面绑定 UserControl 的一些命令。
问题是如果按钮的命令可以执行则更新条件。
就我而言,我想:
//PseudoCode
CurrentPage != FirstPage
&& CurrentPage.CanGoToPrevious
但我不知道如何制作 DelegateCommand
并要求他们在 CurrentPage.CanGoToPrevious
的依赖性 属性 发生变化时再次检查其状况?
嗯,通常在 WPF 中,当人们想要强制某些控件刷新其命令 CanExecuted 时,他们使用 CommandManager.RequerySuggested 事件和 CommandManager.InvalidateRequerySuggested 方法。但是我不喜欢那样,也从不那样做,因为它非常低效(所以我不会详细介绍)。所以,我认为最好的方法是:
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();
}
}
它接受多个布尔值(null 被视为 false)并对它们进行求值。现在 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 属性。