18

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
  • I have enabled that for text box values earlier and the method I have implemented is shown down there Commented Aug 4, 2015 at 10:59

4 Answers 4

22

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();
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

3

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.

2 Comments

But, how can I pass the text property of TextBox to the CanExecute method?
np please mark it as an answer if it worked for you.
1

In straightforward words, you need the following:

  1. Let's first create our own delegate command:
public class DelegateCommand : DelegateCommandBase
{
    private Action _executeMethod;
    private Func<bool> _canExecute;
    
    public DelegateCommand(Action executeMethod)
        : this(executeMethod, () => true) {}
   
    public DelegateCommand(Action executeMethod, Func<bool> _canExecute): base()
    {
        if (executeMethod == null || _canExecute == null) {         
              throw new ArgumentNullException(nameof(executeMethod),      
                              Resources.DelegateCommandDelegatesCannotBeNull);
        }

        _executeMethod = executeMethod;
        _canExecute = _canExecute;
    }

    public void Execute() => _executeMethod();  
    public bool CanExecute() => _canExecute();
    
    protected override void Execute(object parameter) => Execute();
    protected override bool CanExecute(object parameter) => CanExecute();

    public DelegateCommand ObservesProperty<T>(Expression<Func<T>> propertyExpression)
    {
        ObservesPropertyInternal(propertyExpression);
        return this;
    }
    
    public DelegateCommand ObservesCanExecute(Expression<Func<bool>> canExecuteExpression)
    {
        _canExecute = canExecuteExpression.Compile();
        ObservesPropertyInternal(canExecuteExpression);
        return this;
    }
}

Here, DelegateCommandBase is actually from Prism.Commands namespace.

If you don't use Prism as an MVVM framework for WPF, you can create your own copy of DelegateCommandBase (look for the solution here).

  1. In your View Model, create a member with type DelegateCommand and initialize it in the constructor:
public class MyViewModel
{
    private DelegateCommand _okCommand;
    public DelegateCommand OkCommand
    {
        get => _okCommand;
        set => SetProperty(ref _okCommand, value);
    }
        
    public MyViewModel() 
    {
        OkCommand = new PrismCommands.DelegateCommand(OkCommandHandler,
                                                      OkCanExecuteCommandHandler);
    }
    
    private void OkCommandHandler()
    {
        // ...
    } 
    
    // This is important part: need to return true/false based
    // on the need to enable or disable item
    private bool OkCanExecuteCommandHandler() =>
        return some_condition_to_enable_disable_item;   
}

Note: make sure to raise execution changed event, every time something changes that can affect some_condition_to_enable_disable_item condition behavior.

For example, in the case of Prism, you can call RaiseCanExecuteChanged method once a change happens related to the condition (in our case OkCommand.RaiseCanExecuteChanged();).

Small hint: for Telerik WPF Controls, you need to call InvalidateCanExecute() instead of RaiseCanExecuteChanged().


Finally, our XAML will look like this:

<Button x:Name="btnOk"
        Content="Ok"
        Command="{Binding OkCommand}"/>

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.