wpf - 如何使用 Prism 6 正确制作 CanExecute 触发器

标签 wpf mvvm prism delegatecommand

我有一个模型

public class Irritant : BindableBase
{
    private short _id;
    private string _name;
    private string _description;

    public short Id
    {
        get { return _id; }
        set { SetProperty(ref _id, value); }
    }

    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    public string Description
    {
        get { return _description; }
        set { SetProperty(ref _description, value); }
    }


    public Irritant()
    {
        Id = 0;
        Name = "";
        Description = "";       
    }
}

然后我的 ViewModel 有两个版本
public class IrritantViewModel : BindableBase
{
    private IrritantDb db = new IrritantDb();


    //Version 1 - The Model's property is coded in IrritantViewModel
    //private short _id;
    //private string _name = "Alen";
    //private string _description;

    //public short Id
    //{
    //    get { return _id; }
    //    set { SetProperty(ref _id, value); }
    //}

    //public string Name
    //{
    //    get { return _name; }
    //    set { SetProperty(ref _name, value); }
    //}

    //public string Description
    //{
    //    get { return _description; }
    //    set { SetProperty(ref _description, value); }
    //}


    //Version2 - I use the Irritant Model as property of IrritantViewModel
    private DateTime? _lastUpdated;
    private Irritant _entity;

    public Irritant Entity
    {
        get { return _entity; }
        set { SetProperty(ref _entity, value); }
    }

    public DateTime? LastUpdated
    {
        get { return _lastUpdated; }
        set { SetProperty(ref _lastUpdated, value); }
    }

    public DelegateCommand UpdateCommand { get; set; }

    public IrritantViewModel()
    {
        Entity = new Irritant();

        //Version1
        //UpdateCommand = new DelegateCommand(EditCommand, CanExecute).ObservesProperty(() => Name);

        //Version2
        UpdateCommand = new DelegateCommand(EditCommand, CanExecute).ObservesProperty(() => Entity.Name);
    }

    private bool CanExecute()
    {
        //Version1
        //switch (Name)
        //{
        //    case null:
        //        return false;
        //    case "":
        //        return false;
        //}


        //Version2
        switch (Entity.Name)
        {
            case null:
                return false;
            case "":
                return false;
        }

        return true;
    }

    private void EditCommand()
    {
        LastUpdated = DateTime.UtcNow;
    }
}

这是我的观点
public partial class IrritantView : UserControl
{
    public IrritantView()
    {
        InitializeComponent();
        DataContext = new IrritantViewModel();
    }
}

<Grid >
    <ScrollViewer>
        <StackPanel MinWidth="200">

        <TextBlock Text="Irritant"  />



        <!--Version 1-->
                <!--<TextBlock Text="Name" />
                <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
                <TextBlock Text="Description" />
                <TextBox Text="{Binding Description, UpdateSourceTrigger=PropertyChanged}" />
                -->


        <!--Version 2-->

            <TextBlock Text="Name" />
            <TextBox Text="{Binding Entity.Name, UpdateSourceTrigger=PropertyChanged}" />
            <TextBlock Text="Description" />
            <TextBox Text="{Binding Entity.Description, UpdateSourceTrigger=PropertyChanged}" />



            <TextBlock Text="Last Updated" />
            <Label Content="{Binding LastUpdated, UpdateSourceTrigger=PropertyChanged}" />
            <Button Content="Save" 
                    Command="{Binding UpdateCommand}"
                    />
        </StackPanel>
    </ScrollViewer>
</Grid>

Version1 工作正常,当绑定(bind)到 Name (TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}") 的 TextBox 为空或为空时,保存按钮将禁用。

但在版本 2 中,保存按钮不会禁用。它只在初始化时调用 CanExecute 方法,删除 TextBox 中的文本不会禁用 Button。我做错什么了?

最佳答案

DelegateCommand不提高 CanExecuteChanged自动触发事件,您必须通过调用 RaiseCanExecuteChanged 手动引发该事件在适当的时候。除了使用 DelegateCommand , 你可以使用 RelayCommand中继 CommandManager.RequerySuggested为您做类似事情的事件。

  • 更改您的命令定义返回 ICommand :
    public ICommand UpdateCommand { get; set; }
    
  • 使用以下命令初始化命令:
    UpdateCommand = new AutoCanExecuteCommand(new DelegateCommand(EditCommand, CanExecute));
    
  • 使用以下类作为包装器:
    public class AutoCanExecuteCommand : ICommand
    {
        public ICommand WrappedCommand { get; private set; }
    
        public AutoCanExecuteCommand(ICommand wrappedCommand)
        {
            if (wrappedCommand == null) 
            {
                throw new ArgumentNullException("wrappedCommand");
            }
    
            WrappedCommand = wrappedCommand;
        }
    
        public void Execute(object parameter)
        {
            WrappedCommand.Execute(parameter);
        }
    
        public bool CanExecute(object parameter)
        {
            return WrappedCommand.CanExecute(parameter);
        }
    
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
    
  • 关于wpf - 如何使用 Prism 6 正确制作 CanExecute 触发器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33459183/

    相关文章:

    wpf - 绑定(bind)在 Checkbox isChecked WPF 中不起作用

    c# - 如何使用RouteUICommand?

    c# - 选择单个单选按钮,wpf

    c# - WPF窗口阴影效果

    c# - Prism.Navigation.INavigationService,是一个接口(interface),无法构造

    c# - Prism 6 : Multiple Views get data from one ViewModel

    c# - 替换本地 : keyword with a path? 的适当方法是什么

    c# - Avalon UI 绑定(bind)错误 "Could not find CLR property"

    c# - WPF ListView SelectedItems 数据绑定(bind) MVVM

    c# - Prism ( View 模型): Ensure a command does not get executed multiple times simultaneously