简体   繁体   English

WPF:列表框项目上下文菜单/菜单项上的命令即使在按钮上也无法正常工作

[英]WPF: Command on listbox item context menu / menu item does not work even though it does on a button

I have a custom RoutedUICommand that works fine when bound to the Command property of a button. 我有一个自定义的RoutedUICommand,当绑定到按钮的Command属性时,它可以正常工作。 Yet when bound to a ConextMenu MenuItem on a Listbox's item it does not work. 但是,当绑定到列表框项目上的ConextMenu MenuItem时,它将不起作用。 The CanExecute method is not called, and thus the item is left disabled in the context menu. CanExecute方法不会被调用,因此该项目在上下文菜单中保持禁用状态。 The CanExecute is called from the button's binding however. 但是,CanExecute是从按钮的绑定中调用的。

In the repo example below, CrawlCommands.AddCredit is the command. 在下面的回购示例中, CrawlCommands.AddCredit是命令。 It is bound to both a button and ListBoxItems. 它绑定到按钮和ListBoxItems。 The Button behaves as expected, but the ListBoxItem does not. Button的行为符合预期,但ListBoxItem却没有。 Right clicking on a list box item does show the context menu, and the menu item's header is dervied from the Command properly, but the CanExecute is never called, so it never knows the command is valid and thus stays disabled. 右键单击列表框项确实会显示上下文菜单,并且菜单项的标题正确地偏离了Command,但是CanExecute从不被调用,因此它永远不知道该命令有效,因此保持禁用状态。

What am I missing? 我想念什么?

<UserControl x:Class="CrawlSpace.TestCommands"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:CrawlSpace"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" Background="#FF020523">


<UserControl.CommandBindings>
    <CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
</UserControl.CommandBindings>

<Grid>

    <Grid.Resources>
        <local:MockData x:Key="TestData"/>
    </Grid.Resources>

    <Grid.Background>
        <SolidColorBrush Color="DarkGray"/>
    </Grid.Background>
    <Grid.RowDefinitions>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>

    <!-- A button with a command, this one works! -->

    <Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>

    <ListBox x:Name="listBox" Margin="10" Background="LightBlue" ItemsSource="{StaticResource TestData}">
        <ListBox.Resources>
            <!-- Define a context menu -->
            <ContextMenu x:Key="ItemMenu">
                <MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
            </ContextMenu>

            <!-- Sets a context menu for each ListBoxItem in the current ListBox -->
            <Style TargetType="{x:Type ListBoxItem}">

                <!-- This menu item will not function even though the button verison above does -->
                <Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
            </Style>
        </ListBox.Resources>

        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding FirstName}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

Refer my code. 请参阅我的代码。 It is working fine for me. 对我来说很好。

<UserControl x:Class="DragDrop_Learning.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         xmlns:local="clr-namespace:DragDrop_Learning"
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
    <CommandBinding Command="local:CrawlCommands.AddCredit" Executed="ExecutedAddCredit" CanExecute="CanExecuteAddCredit"/>
    <CommandBinding Command="local:CrawlCommands.AddCreditBlock" Executed="ExecutedAddCreditBlock" CanExecute="CanExecuteAddCreditBlock"/>
</UserControl.CommandBindings>

<Grid>

    <Grid.Resources>

    </Grid.Resources>

    <Grid.Background>
        <SolidColorBrush Color="DarkGray"/>
    </Grid.Background>
    <Grid.RowDefinitions>
        <RowDefinition Height="7*"/>
        <RowDefinition Height="3*"/>
    </Grid.RowDefinitions>

    <!-- A button with a command, this one works! -->

    <Button x:Name="button" Command="local:CrawlCommands.AddCredit" Content="Add Credit" Margin="10" Grid.Row="1" Width="177"/>

    <ListBox x:Name="listBox" Margin="10" Background="LightBlue" >
        <ListBox.Resources>
            <!-- Define a context menu -->
            <ContextMenu x:Key="ItemMenu">
                <MenuItem Command="local:CrawlCommands.AddCreditBlock"/>
            </ContextMenu>

            <!-- Sets a context menu for each ListBoxItem in the current ListBox -->
            <Style TargetType="{x:Type ListBoxItem}">

                <!-- This menu item will not function even though the button verison above does -->
                <Setter Property="ContextMenu" Value="{StaticResource ItemMenu}"></Setter>
            </Style>
        </ListBox.Resources>

        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding FirstName}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

 public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        List<Person> lst = new List<Person>();
        listBox.ItemsSource = lst;
        lst.Add(new Person() { FirstName="Test"});
    }

    private void CanExecuteAddCredit(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void ExecutedAddCredit(object sender, ExecutedRoutedEventArgs e)
    {

    }
    private void CanExecuteAddCreditBlock(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void ExecutedAddCreditBlock(object sender, ExecutedRoutedEventArgs e)
    {

    }
}

public static class CrawlCommands
{
    public static readonly RoutedUICommand AddCredit = new RoutedUICommand
            (
                    "AddCredit",
                    "AddCredit",
                    typeof(CrawlCommands)
            );

    public static readonly RoutedUICommand AddCreditBlock = new RoutedUICommand
            (
                    "AddCreditBlock",
                    "AddCreditBlock",
                    typeof(CrawlCommands)
            );
}

class Person
{
    private string myVar;

    public string FirstName
    {
        get { return myVar; }
        set { myVar = value; }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM