简体   繁体   中英

Binding Command on dynamically loaded menuitem

I am successfully populating a menuitem with a list of cars. I want each car in the menuitem to be able to fire a command "RemoveCarCommand". On a dynamically loaded menuitem of cars (or anything), I know I need to have the command assigned to each car that is in the menuitem, but I cannot figure out the XAML to do that. Can someone help?

<MenuItem Header="Remove Car" ItemsSource="{Binding AvailableCars}">
    <MenuItem.ItemContainerStyle>
        <Style>
            <Setter Property="MenuItem.Command" Value="{Binding RemoveCarCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

I think you are over thinking your issue, if each menuitem is going to perform the same task just on a different "car", you can just point all of them to the same event handler for click then access the datacontext to find out which one was clicked and thus which car to remove.

<MenuItem Header="Remove Car" ItemsSource="{Binding AvailableCars}" click"removeCar"/>

in CB

private void removeCar(object sender, EventArgs e)
{
    Car car = ((sender as Button).DataContext as Car);

    car.remove();
    //OR
    CarsList.Remove(car);
}

If you absolutely MUST use the command MVVM binding this is what you need:

public class RelayCommand : ICommand
{
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameters)
    {
        return _canExecute == null ? true : _canExecute(parameters);
    }

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

    public void Execute(object parameters)
    {
        _execute(parameters);
    }

    #endregion // ICommand Members
}

Then add this in your class obj for Car:

public class Car
{
    private ICommand _ClickCommand;
    public ICommand ClickCommand
    {
        get
        {
            if (_ClickCommand == null)
            {
                _ClickCommand = new RelayCommand(param => this.Click(param, EventArgs.Empty));
            }
            return _ClickCommand;
        }
    }
}

And this is how you bind to it in WPF:

                <Menu.ItemContainerStyle>
                    <Style TargetType="{x:Type MenuItem}">
                        <Setter Property="Command" Value="{Binding ClickCommand}"/>
                    </Style>
                </Menu.ItemContainerStyle>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM