2009-05-22 21 views
19

Tengo un menú contextual. Está destinado a alguna colección y tiene un ItemTemplate define así:Especificar comando para MenuItem en un DataTemplate

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

itemtemplate es un DataTemplate simple con un TextBlock:

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

Cómo hacer yo ato propiedad Command para Menultem a la propiedad del objeto subyacente ?

Respuesta

24

Creo que se necesita para envolver su TextBlock en un Menultem:

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

pero no tienen un IDE delante de mí en este momento para probar esto. Déjame saber como va.


Parece que es necesario utilizar el ItemContainerStyle como se ve here. Lo siento por que le conduce por el camino equivocado al principio allí - pero tengo delante de un IDE y esto funciona:

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

En realidad, esto se sumará a TextBlock colección de elementos de la Menultem. Y también coloca MenuItem dentro de otro MenuItem. – arconaut

+0

Pero con su publicación comencé a pensar en la creación de plantillas de MenuItem, esto podría ser lo que necesito. – arconaut

+0

Sí, eso es lo que me probé hace solo un minuto. – arconaut

4

Aunque esto es sólo una ligera variación en la respuesta de Martin Harris, pensé que me gustaría compartir de todos modos. He encontrado que es más útil especificar un comando único para toda la colección y también enviar a lo largo de un CommandParameter:

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

A continuación, puede determinar qué hacer en el controlador para el comando:

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

Funcionó bien para mí. Gracias –

-2

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 
    } 
+0

Por favor, no publique respuestas "protegidas" en la pila. El propósito es compartir conocimiento, no bloquearlo. – davids

+0

Respondió una pregunta que no le hizo, Guru. –

Cuestiones relacionadas