WPF MVVM command canexecute enable/disable button

2020-02-01 04:56发布

问题:

I want to enable RibbonButton when textbox property text isn't null. Disable RibbonButton when textbox property text is null. I want to use CanExecute method in ICommand for it. How can I do it?

View:

 <Custom:RibbonButton
                        LargeImageSource="..\Shared\img\save_diskete.png"
                        Label="Save"
                        Command="{Binding ButtonCommand}">
                    </Custom:RibbonButton>

ViewModel

class KomentarViewModel:BaseViewModel
    {
        #region Data
        private ICommand m_ButtonCommand;
        public ICommand ButtonCommand
        {
            get
            {
                return m_ButtonCommand;
            }
            set
            {
                m_ButtonCommand = value;
            }
        }
        private string textKomentar;
        public string TextKomentar
        {
            get
            {
                return this.textKomentar;
            }
            set
            {
                // Implement with property changed handling for INotifyPropertyChanged
                if (!string.Equals(this.textKomentar, value))
                {
                    textKomentar = value;
                    OnPropertyChanged("TextKomentar");
                }
            }
        }        
        private ObservableCollection<Komentar> allCommentsInc;
        public ObservableCollection<Komentar> AllCommentsInc
        {
            get
            {
                return allCommentsInc;
            }
            set
            {
                allCommentsInc = value;
                OnPropertyChanged("AllCommentsInc");
            }
        }

        public int idIncident { get; private set; }
        public Incident incident { get; private set; }
        #endregion

        #region Constructor
        public KomentarViewModel(int id)
        {
            CC_RK2Entities context = new CC_RK2Entities();
            this.idIncident = id;

            AllCommentsInc = new ObservableCollection<Komentar>(context.Komentar.Where(a => a.Incident_id == idIncident));
            incident = context.Incident.Where(a => a.id == idIncident).First();

            //ButtonCommand = new RelayCommand(new Action<object>(ShowMessage));
        }
        #endregion        

        #region Methods
        //ukaz napsany text
        public void ShowMessage(object obj)
        {
            //MessageBox.Show(obj.ToString());
            MessageBox.Show(this.TextKomentar);
        }
}

RelayCommand

namespace Admin.Shared.Commands
{
    class RelayCommand : ICommand
    {
        private Action<object> _action;

        public RelayCommand(Action<object> action)
        {
            _action = action;
        }

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return true;            
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
                _action(parameter);
        }

        #endregion
    }
}

回答1:

You need to modify your RelayCommand class like this

  class RelayCommand : ICommand
{
    private Action<object> _action;
    private Func<bool> _func;  

    public RelayCommand(Action<object> action,Func<bool> func)
    {
        _action = action;
        _func = func;
    }

    public void RaiseCanExecuteChanged()
    {
        if(CanExecuteChanged!=null)
            CanExecuteChanged(this,new EventArgs());
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        if (_func != null)
           return _func();
        return true;
    }



    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }

    #endregion
}

Initialize ButtonCommand as

ButtonCommand = new RelayCommand((s) => ShowMessage(s),()=>!string.IsNullOrEmpty(TextKomentar));

RaiseCanExcuteChanged from the setter of Text property

        public string TextKomentar
    {
        get
        {
            return this.textKomentar;
        }
        set
        {
            // Implement with property changed handling for INotifyPropertyChanged
            if (!string.Equals(this.textKomentar, value))
            {
                textKomentar = value;
                OnPropertyChanged("TextKomentar");
            }
            ButtonCommand.RaiseCanExecuteChanged();
        }
    }


回答2:

implement this for canexecute:

public bool CanExecute(object parameter)
        {if(thistext available)
            return true; 
         else
            return false;  
        }

Since, CanExecuteChanged is raised when the CanExecute method of an ICommand gets changed. it gets invoked when some command that could change canexecute. and can execute changed should be changed to this:

public event EventHandler CanExecuteChanged {
    add {
        CommandManager.RequerySuggested += value;
    }
    remove {
        CommandManager.RequerySuggested -= value;
    }
}

EDIT

in your view model constructor:

m_ButtonCommand= new RelayCommand(Submit, CanSubmit);

now method for this submit:
 private bool CanSubmit(object obj)
        {
            if(thistext available)
                return true; 
             else
                return false;  

        }
 public void Submit(object _)
  {//... code}

 public event EventHandler CanExecuteChanged {
        add {
            CommandManager.RequerySuggested += value;
        }
        remove {
            CommandManager.RequerySuggested -= value;
        }
    }

do it like this.



回答3:

Last time I used Microsoft.Practices.Prism.Commands namesapce from Microsoft.Practices.Prism.dll. Class DelegateCommand has own RaiseCanExecuteChanged() method. So the benifit is you don't have to write yout own implementation of ICommand.

XAML:

<StackPanel>
    <CheckBox IsChecked="{Binding IsCanDoExportChecked}" />
    <Button Command="{Binding ExportCommand}" Content="Export" />
</StackPanel>

ViewModel:

public class ViewModel
{
    public DelegateCommand ExportCommand { get; }

    public ViewModel()
    {
        ExportCommand = new DelegateCommand(Export, CanDoExptor);
    }

    private void Export()
    {
        //logic
    }

    private bool _isCanDoExportChecked;

    public bool IsCanDoExportChecked
    {
        get { return _isCanDoExportChecked; }
        set
        {
            if (_isCanDoExportChecked == value) return;

            _isCanDoExportChecked = value;
            ExportCommand.RaiseCanExecuteChanged();
        }
    }

    private bool CanDoExptor()
    {
        return IsCanDoExportChecked;
    }
}


标签: c# wpf mvvm