2014-03-07 27 views
1

這讓我生氣了好幾天了!WPF MenuItem Command.Executed沒有發射,但Command.CanExecute沒有

我無法讓命令的執行部分在我的菜單的'1級'以下的任何東西上觸發。我可以看到'CanExecute'回調總是在所有菜單項上調用,並且回調總是返回true。

請有人指出我在正確的方向嗎?我知道我可以在MyTypes中添加一個ICommand實現:MyMenuDescriptorType,但這不適合我試圖實現的模型。

提前感謝

private void CreateActionCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
{ 
    e.CanExecute = true; 
    e.Handled = true; 
} 
private void CreateActionCommand_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
    Debug.WriteLine("This only happens on Level 1"); 
} 

<UserControl.Resources> 
    <ResourceDictionary> 
     <RoutedUICommand x:Key="CreateAction" Text="CreateAction"/> 
    </ResourceDictionary> 
</UserControl.Resources>  
<Grid x:Name="LayoutRoot"> 
    <Menu> 
     <Menu.CommandBindings> 
      <CommandBinding Command="{StaticResource CreateAction}" Executed="CreateActionCommand_Executed" CanExecute="CreateActionCommand_CanExecute"/>    
     </Menu.CommandBindings>   
     <Menu.Resources> 
      <Style x:Key="MyMenuStyle" TargetType="{x:Type MenuItem}"> 
       <Setter Property="Header" Value="{Binding Description}"/> 
       <Setter Property="Command" Value="{StaticResource CreateAction}" /> 
       <Setter Property="CommandParameter" Value="{Binding}"/> 
       <Setter Property="CommandTarget" Value="{Binding Path=., RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"/>     
      </Style>           
     </Menu.Resources>   
     <MenuItem Header="Root Level"> 
      <MenuItem Header="Level 1" ItemsSource="{Binding MyListOfThings}" ItemContainerStyle="{StaticResource MyMenuStyle}"> 
       <MenuItem.Resources> 
        <HierarchicalDataTemplate 
         DataType="{x:Type MyTypes:MyMenuDescriptorType}" 
         ItemsSource="{Binding Path=Children}" 
         ItemContainerStyle="{StaticResource MyMenuStyle}"/> 
       </MenuItem.Resources> 
      </MenuItem> 
     </MenuItem> 
    </Menu> 
</Grid> 

更新:因爲我已經摸索出了什麼事錯了。我的簡化示例沒有更新屬性「MyListOfThings」。如果我更新菜單的PreviewMouseLeftButtonDown事件中的'MyListOfThings',那麼控件會做出奇怪的事情,並且命令不會觸發。但是,如果我更新MouseOver事件中的屬性,那麼一切都按預期工作!

我不知道這是爲什麼。也許有人可以解釋?

回答

0

您可以嘗試執行一個DelegateCommand,您可以找到snippet code here

在你的菜單項後,會看起來像:

<MenuItem Header="DoSomething" Command="{Binding DoSomethingCommand}"/> 

,並在您的視圖模型:

public MainViewModel() 
    { 
     DoSomethingCommand= new DelegateCommand(DoSomethingCommandExec, DoSomethingCommandCanExec); 
    } 

    public ICommand DoSomethingCommand{ get; private set; } 

    private bool DoSomethingCommandCanExec() 
    { 
     return true; 
    } 

    private void DoSomethingCommandExec() 
    { 
     // DoSomethingCommand 
    } 

我認爲這是實現它的好方法。每個MenuItem都有一個Command。您可以將Menuitems放入MenuItem中,該​​MenuItem可以綁定到與此處相同的命令。

喜歡:

<MenuItem Header="DoSomething" Command="{Binding DoSomethingCommand}"> 
    <MenuItem Header="DoSomething" Command="{Binding DoSomethingCommand}"/> 
</MenuItem> 

希望幫助。

問候!

0

根據​​的問題。它的工作對我來說:

HAML:

<Window x:Class="WpfApplication3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication3" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <ResourceDictionary> 
     <ContextMenu x:Key="ContextMenu1"> 
      <MenuItem Header="Menu1" Command="{Binding PlacementTarget.Tag.Menu1Executed, RelativeSource={RelativeSource AncestorType=ContextMenu}}" /> 
     </ContextMenu> 
    </ResourceDictionary> 
</Window.Resources> 

<Grid ShowGridLines="True" ContextMenu="{DynamicResource ContextMenu1}" Tag="{Binding}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="100*"/> 
    </Grid.RowDefinitions> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="100*"/> 
    </Grid.ColumnDefinitions> 

    <Label Grid.Column="1" Content="Content" Margin="2"/> 
</Grid> 

CS:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new MainWindowViewModel(); 
    } 
} 

public class MainWindowViewModel 
{ 
    public MainWindowViewModel() 
    { 
     Menu1Executed = new DelegateCommand(ShowMenu1); 
    } 

    public ICommand Menu1Executed { get; set; } 

    private void ShowMenu1(object obj) 
    { 
     // Yay! 
    } 
} 

public class DelegateCommand : ICommand 
{ 
    private readonly Action<object> execute; 
    private readonly Predicate<object> canExecute; 

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

    public DelegateCommand(Action<object> execute, Predicate<object> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 

     this.execute = execute; 
     this.canExecute = canExecute; 
    } 

    #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 
}