带有上下文菜单的 WPF 列表框可以执行直到选中某些内容才调用
WPF listbox with contextmenu canexecute not called until something selected
我有一个 ListBox ItemTemplate 绑定到我的项目的 ObservableCollection。
目前,我正在尝试实现 Cut/Copy/Paste/SelectAll(为了简短起见,我将在这里显示 select 所有...)
<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;
}
当我第一次 运行 程序并右键单击列表框时,"Select All" 上下文菜单始终禁用(并且永远不会调用 SelectAll_CanExecute),直到我 select 东西。
有什么方法可以让它像它应该的那样工作吗?
(并且没有自动 selecting 第一项或让用户必须这样做)
谢谢!
如前所述,这是一个已知错误 here。如果window的主要焦点范围内没有焦点元素,CanExecute
路由将停在ContextMenu
,因此不会到达CommandBinding
Window、一个解决方法 是将 MenuItem
的 CommandTarget
绑定到主 window,如以下代码所示:
<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。这家伙是个天才!!!
我有一个 ListBox ItemTemplate 绑定到我的项目的 ObservableCollection。 目前,我正在尝试实现 Cut/Copy/Paste/SelectAll(为了简短起见,我将在这里显示 select 所有...)
<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;
}
当我第一次 运行 程序并右键单击列表框时,"Select All" 上下文菜单始终禁用(并且永远不会调用 SelectAll_CanExecute),直到我 select 东西。 有什么方法可以让它像它应该的那样工作吗? (并且没有自动 selecting 第一项或让用户必须这样做)
谢谢!
如前所述,这是一个已知错误 here。如果window的主要焦点范围内没有焦点元素,CanExecute
路由将停在ContextMenu
,因此不会到达CommandBinding
Window、一个解决方法 是将 MenuItem
的 CommandTarget
绑定到主 window,如以下代码所示:
<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。这家伙是个天才!!!