Подтвердить что ты не робот

Укажите команду для MenuItem в DataTemplate

У меня есть контекстное меню. Он связан с некоторой коллекцией и имеет определенный ItemTemplate следующим образом:

<ContextMenu
    ItemsSource={Binding ...}
    ItemTemplate={StaticResource itemTemplate}
    />

itemTemplate - это простой DataTemplate с TextBlock:

<DataTemplate x:Key="itemTemplate">
    <TextBlock Text={Binding ...} />
</DataTemplate>

Как связать свойство Command для MenuItem с базовым свойством объекта?

4b9b3361

Ответ 1

Я думаю, вам нужно обернуть свой TextBlock в MenuItem:

<DataTemplate x:Key="itemTemplate">
    <MenuItem Command={Binding ...}>
        <TextBlock Text={Binding ...} />
    </MenuItem>
</DataTemplate>

Но у меня нет IDE передо мной прямо сейчас, чтобы попробовать это. Дайте мне знать, как это происходит.


Похоже, вам нужно использовать ItemContainerStyle, как показано здесь. Извините за то, что вы навели неправильный путь в начале, но я встал перед IDE, и это работает:

<ContextMenu.ItemContainerStyle>
    <Style TargetType="MenuItem">
        <Setter Property="Command" Value="{Binding ...}"/>
    </Style>
</ContextMenu.ItemContainerStyle>

Ответ 2

Хотя это лишь небольшая вариация ответа Мартина Харриса, я думал, что все равно поделюсь ею. Я нашел более полезным указать одну команду для всей коллекции, а также отправить по CommandParameter:

<MenuItem.ItemContainerStyle>
    <Style TargetType="MenuItem">
       <Setter Property="Command" Value="{x:Static v:ViewModel.CommandForAll}"/>
       <Setter Property="CommandParameter" Value="{Binding ValueForCommand}"/>
    </Style>
</MenuItem.ItemContainerStyle>

Затем вы можете определить, что делать в обработчике команды:

private void CommandForAll_Executed(object sender, ExecutedRoutedEventArgs e)
{
    var cmdParam = e.Paramater as ExpectedType
    if (cmdParam != null)
        //DoStuff...
}

Ответ 3

MainWindow.xaml

<Window.ContextMenu>
        <ContextMenu x:Name="winCM">

            <!--<ContextMenu.ItemContainerStyle>
                <Style TargetType="MenuItem">
                    <Setter Property="Command" Value="{Binding CloseCommand}" />
                </Style>
            </ContextMenu.ItemContainerStyle>-->

            <MenuItem Name="menuItem_Close" Header="Close" Command="{Binding Path=DataContext.CloseCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>

            <!--Command="{Binding Path=PlacementTarget.DataContext.CloseCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"-->
        </ContextMenu>
    </Window.ContextMenu>

MainWindow.cs

 public partial class MainWindow : Window 
{
        private bool _canCloseCommandExecute;

        public bool CanCloseCommand

        {
            get
            {
                return _canCloseCommandExecute;
            }
        }
        private RelayCommand _closeCommand;
        public ICommand CloseCommand
        {
            get
            {
                if (_closeCommand == null)
                {
                    _closeCommand =  new RelayCommand(p => this.OnClose(p), p => CanCloseCommand);
                }
                return _closeCommand;
            }
        }

        public void OnClose(object obj)
        {
            Close();
        }

        public MainWindow()
        {
            InitializeComponent();

            /* This will do the trick here */
            this.winCM.DataContext = this;
            this._canCloseCommandExecute = true;
        }
}

RelayCommand.cs

public class RelayCommand : ICommand
    {
        #region Fields

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

        #endregion // Fields

        #region Constructors

        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        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 parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

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

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

        #endregion // ICommand Members
    }