wpfselecteditemcommandparameter

WPF selectedItem on Menu or get commandparameter in viewmodel


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


Solution

  • 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'
    }