简体   繁体   中英

WPF : MenuItem.CommandParameter binding set to null

I have the following ContextMenu defined for my data grid:

<igDP:XamDataGrid.ContextMenu>
    <ContextMenu ItemsSource="{Binding CommandViewModels}"                     >
        <ContextMenu.ItemContainerStyle>
            <Style TargetType="MenuItem">
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
                <Setter Property="Header" Value="{Binding Name}" />
                <Setter Property="Icon" Value="{Binding Icon}" />
            </Style>
        </ContextMenu.ItemContainerStyle>
    </ContextMenu>
</igDP:XamDataGrid.ContextMenu>

A CommandViewModel class is defined as follows:

public class CommandViewModel : ICommandViewModel
    {
        public CommandViewModel(string name, Image icon, ICommand command, object commandParameter = null, int index = 0)
        {
            Name = name;
            Icon = icon;
            Command = command;
            CommandParameter = commandParameter;
            Index = index;
        }

        public string Name { get; set; }
        public Image Icon { get; set; }
        public ICommand Command { get; set; }
        public object CommandParameter { get; set; }
        public int Index { get; set; }     
    }

When I right click on a row in the grid, each MenuItem of the ContextMenu is correctly styled. The icon, label and command of the MenuItem is as expected. However, the command parameter, CommandViewModel.CommandParameter, that should be passed as argument to the RelayCommand bound to MenuItem.Command is null.

I am fairly certain that the command parameter available for the binding is not null. This is WPF application running on .NET 4.0.

Anyone experienced this?

This is apparently a known problem with the CommandParameter binding.

Since I did not want to edit Prism code, I ended up using the CommandParameterBehavior class defined in the referenced CodePlex post.

Modifying my custom RelayCommand class to implement IDelegateCommand as follows:

 public class RelayCommand : IDelegateCommand
{
    readonly protected Predicate<object> _canExecute;
    readonly protected Action<object> _execute;      

    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        _canExecute = canExecute;
        _execute = execute;          
    }

    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }      

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

    public event EventHandler CanExecuteChanged;

    public virtual void Execute(object parameter)
    {
        _execute(parameter);
    }      
}

and modifying my original style to use the CommandParameterBehavior like so:

 <Style TargetType="MenuItem">
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
                <Setter Property="Header" Value="{Binding Name}" />
                <Setter Property="Icon" Value="{Binding Icon}" />
                <Setter Property="utility:CommandParameterBehavior.IsCommandRequeriedOnChange" Value="true"
            </Style>

The CommandParameter is now passed correctly.

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