WPF MenuItem Command.Executed未触发,但Command.CanExecute执行

时间:2014-03-07 16:31:46

标签: c# wpf hierarchicaldatatemplate commandbinding

这让我疯了几天了!

我无法让命令的Executed部分触发菜单中“Level 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'。如果我在Menu的PreviewMouseLeftButtonDown事件中更新'MyListOfThings',那么控件会执行奇怪的操作并且命令不会触发。但是,如果我在MouseOver事件中更新属性,那么一切都按预期工作!

我不确定为什么会这样。也许有人可以解释一下?

2 个答案:

答案 0 :(得分:0)

您可以尝试实施DelegateCommand,您可以找到snippet code here

在您的MenuItem之后,

将如下所示:

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

并在您的ViewModel中:

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 Header="DoSomething" Command="{Binding DoSomethingCommand}">
    <MenuItem Header="DoSomething" Command="{Binding DoSomethingCommand}"/>
</MenuItem>

希望帮助。

问候!

答案 1 :(得分:0)

基于this问题。它对我有用:

HAML:

eventList.clear();

cs:

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