2

I am searching for hours to fix a simple problem. I wanted to work with "SelectedItem" on my menuItems, but after hours of stackoverflow I saw that's impossible. I found a lot about "CommandParameter" but I don't understand how it works. This is what I want to do: I have a menu with "background1, background2,..." . If you select a background in the menu, I want to set that selected background as background.

It's a schoolproject, so we have to use MVVM and no codebehind is allowed. How can I "use" the Commandparameter in my ViewModel?

This is my mainWindow.xaml:

                <Toolbar>
                  <Menu>
                    <MenuItem Header="Background" ItemsSource="{Binding Backgrounds}">
                        <MenuItem.ItemTemplate>
                            <DataTemplate>
                                <MenuItem Header="{Binding Name}" Command="{Binding ChangeBackgroundCommand}" CommandParameter="{Binding Name}"/>
                            </DataTemplate>
                        </MenuItem.ItemTemplate>
                    </MenuItem>
                  </Menu>
                </Toolbar>

This is a part of my mainWindowViewModel:

public MainWindowViewModel()
    {
        //load data
        BackgroundDataService bds = new BackgroundDataService();
        Backgrounds = bds.GetBackgrounds();

        //connect command
        WijzigBackgroundCommand = new BaseCommand(WijzigBackground);
    }
private void ChangeBackground()
    {
        //I want here the name of the selected menuItem (by parameter?)
    }

}

We use a baseCommand class(I don't want to change this class because its standard I think):

class BaseCommand : ICommand
{
    Action actie;

    public BaseCommand(Action Actie)
    {
        actie = Actie;
    }

    public event EventHandler CanExecuteChanged;

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

    public void Execute(object parameter)
    {
        actie.Invoke();
    }
}

I use stackoverflow a lot :-) this is my firts post/question, I hope it's clear

  • Sadly I make a mistake with translation: "wijzig" is dutch for "change" (I didn't translate everything) but that is correct/not the problem, sorry – AxelPauwels Mar 27 '17 at 19:49
  • CommandParameter="{Binding}" would pass the DataContext of the menu item into the command (better than just passing in the Name). The problem is that the BaseCommand implementation is crap--it should take an Action (or more properly be generic and take an Action), and when `Execute` is called, it should pass the parameter object to the Action. That way, in your view model (which controls the Action passed into the BaseCommand) you can grab the command parameter and change the background accordingly. –  Mar 27 '17 at 19:53
  • I will try to changed it then, I will reply when it's solved, thanks – AxelPauwels Mar 27 '17 at 19:59

1 Answers1

1

Try this:

class BaseCommand<T> : ICommand
{
    private readonly Action<T> _executeMethod = null;
    private readonly Func<T, bool> _canExecuteMethod = null;

    public BaseCommand(Action<T> executeMethod)
        : this(executeMethod, null)
    {
    }

    public BaseCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
    {
        _executeMethod = executeMethod;
        _canExecuteMethod = canExecuteMethod;
    }

    public bool CanExecute(T parameter)
    {
        if (_canExecuteMethod != null)
        {
            return _canExecuteMethod(parameter);
        }
        return true;
    }

    public void Execute(T parameter)
    {
        if (_executeMethod != null)
        {
            _executeMethod(parameter);
        }
    }

    public event EventHandler CanExecuteChanged;

    bool ICommand.CanExecute(object parameter)
    {
        if (parameter == null &&
            typeof(T).IsValueType)
        {
            return (_canExecuteMethod == null);
        }
        return CanExecute((T)parameter);
    }

    void ICommand.Execute(object parameter)
    {
        Execute((T)parameter);
     }
}

Use it like this:

public MainWindowViewModel()
{
    // ...

    // connect command
    WijzigBackgroundCommand = new BaseCommand<YourBackgroundClass>(
         (commandParam) => WijzigBackground(commandParam), 
         (commandParam) => CanWijzigBackground(commandParam));
}

private void WijzigBackground(YourBackgroundClass param)
{
    // Use 'param'
}

private bool CanWijzigBackground(YourBackgroundClass param)
{
    // Use 'param'
}
janonimus
  • 1,911
  • 2
  • 11
  • 11