0

I have two combo boxes in a form and a button. What i want to do is enable the button only if both the combo boxes have values selected in them.

My xaml

    <Button Content="Generate Report" 

            Command="{Binding GenerateReportCommand}"
            Margin="30,250,0,0">

              <ComboBox Name="combo1" 
              ItemsSource="{Binding BannerValues}"
              SelectedItem="{Binding item1}">

              <ComboBox Name="combo2" 
              ItemsSource="{Binding BannerValues}"
              SelectedItem="{Binding item2}">   

I have a view model where all my bindings are defined.

class DataSource : INotifyPropertyChanged
{

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
    public DataSource()
    {
        item1= load();
        item2=load();// have some custome function to load the values for combobox
    }
public ICommand GenerateReportCommand
    {
        get
        {
            return new CommandHandler(() => GenerateReport(item1,item2), true);
        }
    }

I have a separate class for commandhandler and will be in a seaprate file.

public class CommandHandler : ICommand
{
    private Action _action;
    private bool _canExecute;
    public CommandHandler(Action action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

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

    public event EventHandler CanExecuteChanged;

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

how do i disable/enable the button based on the two combo boxes. Searching in the internet found that we can do using multidatatrigger. But i want to achieve using this command hanlder canexecute function

Boopal S
  • 123
  • 1
  • 1
  • 11
  • `public CommandHandler(Action action, bool canExecute)`. the first step will to pass here a `Func canExecute` instead of bool constant. and then re-evalute that fuction from time to time. anyway: why not search the internet for ICommand implementation which can do it, instead of writing your own?? or better: search the internet for MVVM framework for wpf – ASh Mar 23 '18 at 10:57
  • found this link and followed jack_tux solution. worked well https://stackoverflow.com/questions/1468791/wpf-icommand-mvvm-implementation – Boopal S Mar 23 '18 at 11:20
  • Possible duplicate of [WPF ICommand MVVM implementation](https://stackoverflow.com/questions/1468791/wpf-icommand-mvvm-implementation) – ASh Mar 23 '18 at 12:02

1 Answers1

0

Here's an other take on it:

// basic concrete ICommand implementation
abstract class CommandBase : ICommand
{
    public event EventHandler CanExecuteChanged;

    protected void OnCanExecuteChanged ( ) => CanExecuteChanged?.Invoke ( this, EventArgs.Empty );

    public virtual bool CanExecute ( object parameter ) => true;

    public abstract void Execute ( object parameter );
}

// Now, a more specialized command. 
class GenerateReportCommand : CommandBase
{
    // In the GOF version of the Command pattern, you inject the context in the command's constructor
    public GenerateRepportCommand ( MainViewModel context )
    {
        _context = context;

        // The viewmodel will tell us when to refresh our CanExecute
        context.PropertyChanged += ( sender, e ) => OnCanExecuteChanged ( );
    }

    private MainViewModel _context;

    public override bool CanExecute ( object parameter ) =>    !string.IsNullOrWhiteSpace ( _context.Item1 ) 
                                                            && !string.IsNullOrWhiteSpace ( _context.Item2 );

    public override void Execute ( object parameter )
    {

        // someDependency.GenerateReport ( _context.Item1, _context.Item2 );
    }
}

// Now for the viewmodel side of things
class MainViewModel : ViewModelBase
{
    public MainViewModel ( )
    {
        // You could inject your "report generating" dependencies through here
        GenerateReport = new GenerateReportCommand ( this );
    }

    public string Item1 { get { return _item1; }
                          set { _item1 = value; OnPropertyChanged ( ); } }
    private string _item1;

    public string Item2 { get { return _item2; }
                          set { _item2 = value; OnPropertyChanged ( ); } }
    private string _item2;

    public ICommand GenerateReport { get; private set; }
}
Seb
  • 620
  • 1
  • 5
  • 11