带有contextmenu canexecute的WPF列表框在选择某些内容之前不会被调用



我有一个ListBox,ItemTemplate绑定到我的项目的ObservableCollection。目前,我正在尝试实现剪切/复制/粘贴/全选(为了简短起见,我只在这里显示全选…)

<UserControl.CommandBindings>
    <CommandBinding Command="SelectAll" CanExecute="SelectAll_CanExecute" Executed="SelectAll_Executed"/>
</UserControl.CommandBindings>
<ListBox x:Name="listbox" 
         ItemsSource="{Binding}" 
         Background="Transparent" 
         SelectionMode="Extended"
         ScrollViewer.VerticalScrollBarVisibility="Auto">
    <ListBox.ContextMenu>
        <ContextMenu>
            <MenuItem Command="SelectAll" />
        </ContextMenu>
    </ListBox.ContextMenu>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Background="Transparent">
                <CheckBox Name="cbEnabled" IsChecked="{Binding Enabled, Mode=TwoWay}" Margin="0,2,0,0"/>
                <TextBlock Text="{Binding Name}" Padding="5,0,0,0"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>

这是canexecute的代码索引:

    private void SelectAll_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = listbox.Items.Count > 0;
        e.Handled = true;
    }

当我第一次运行程序并右键单击列表框时,"全选"上下文菜单总是被禁用(并且永远不会调用SelectAll_CanExecute),直到我选择了一些东西。有什么办法让它像看起来应该的那样发挥作用吗?(并且没有自动选择第一个项目或让用户必须这样做)

谢谢!

这是这里提到的一个已知错误。如果窗口的主焦点范围中没有焦点元素,则CanExecute路由将停止在ContextMenu,因此它将无法到达窗口上的CommandBinding一个解决方法是将MenuItemCommandTarget绑定到主窗口,如下代码所示:

<ListBox.ContextMenu>
    <ContextMenu>
        <MenuItem Command="SelectAll"
                    CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}">
        </MenuItem>
    </ContextMenu>
</ListBox.ContextMenu>

以下是完整的代码:

<UserControl x:Class="ListBoxStyle.ListBoxUserControl"
             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" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.CommandBindings>
        <CommandBinding Command="SelectAll" CanExecute="SelectAll_CanExecute" Executed="SelectAll_Executed"/>
    </UserControl.CommandBindings>
    <Grid>
        <ListBox x:Name="listbox" 
             Background="Transparent" 
             SelectionMode="Extended"
             ScrollViewer.VerticalScrollBarVisibility="Auto">
            <ListBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Command="SelectAll"
                    CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}">
                    </MenuItem>
                </ContextMenu>
            </ListBox.ContextMenu>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Background="Transparent">
                        <CheckBox Name="cbEnabled" IsChecked="{Binding Enabled, Mode=TwoWay}" Margin="0,2,0,0"/>
                        <TextBlock Text="{Binding}" Padding="5,0,0,0"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

作为参考。。。我在使用UserControl时也遇到了同样的问题。我有太多的MenuItem,我也想确保不要忘记新MenuItem上的那一行。然后我选择了一种风格:

 <UserControl.Resources>
        <Style TargetType="MenuItem">
            <Setter Property="CommandTarget" Value="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"></Setter>    
        </Style>
...

如果你想对我竖起大拇指。。。把它交给真正发现问题并找到解决方案的Vinkal。这家伙是个天才!!!

最新更新