【问题标题】:Have a commande with the "CanXXXX" listening to multiple properties使用“CanXXXX”命令监听多个属性
【发布时间】:2015-09-04 13:21:13
【问题描述】:

我正在做一个可以显示向导的UserControl(使用 WPF+Prism)。

为此,我有两个控件:WizardWizardPage

我希望我能以这样的事情结束

<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>

我目前卡在 Wizard UserControl 中的命令上。

我会有 3 个Buttons:

  • 上一页
  • 下一步
  • 取消

我想在上面绑定一些UserControl的命令。

问题是如果可以执行按钮的命令,则更新条件。

就我而言,我想:

//PseudoCode
CurrentPage != FirstPage
&& CurrentPage.CanGoToPrevious

但我不知道如何制作DelegateCommand 并要求他们在CurrentPage.CanGoToPrevious 的依赖属性发生变化时再次检查其状况?

【问题讨论】:

    标签: wpf xaml command


    【解决方案1】:

    嗯,通常在 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 属性。

    【讨论】:

    • 好的。所以响应是“否”,没有办法监听多个属性。我知道使用一种方法来检索所有项目的值,但由于我的项目之一是依赖属性,我认为有可能表明当 DP 更改时命令可用性可能会更改。
    猜你喜欢
    • 1970-01-01
    • 2021-01-27
    • 2015-04-28
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-05
    相关资源
    最近更新 更多