WPF 上下文菜单单击事件在一个位置工作,而不在另一个位置工作



我有以下 XAML,它生成一个列表框,其中每个项在扩展器中都包含另一个列表框,并且我已将PageContextMenu定义为顶级列表的上下文菜单和较低级别列表的FrameContextMenu

问题:两者都正确显示,但单击事件仅在顶级上下文菜单上起作用,而不适用于较低级别的上下文菜单。 例如,单击PageContextMenu中的Delete Selected会正确调用关联的处理程序,但单击FrameContextMenu中的Delete Selected Frame(s)不会触发关联的处理程序。 我没有看到任何错误的迹象,即使我在ContextDeleteFrames_Click中放置了一个断点,它也不会被命中。 就好像根本没有与该菜单项关联的处理程序一样。

我已经查看了与上下文菜单不起作用相关的许多其他问题,但似乎都不适用。 嵌套的两个列表框是否有问题?

XAML:

<ListBox Name="PageListBox" ItemsSource="{Binding CurrentPack.Pages}" HorizontalAlignment="Stretch" SelectionMode="Extended">
<ListBox.Resources>
<ContextMenu x:Key="PageContextMenu">
<MenuItem Header="_Add" Name="ContextAddAddPage"/>
<MenuItem Header="_Edit" Name="ContextEditPage"/>
<MenuItem Header="_Delete Selected" Name="ContextDeletePage" Click="ContextDeletePage_Click"/>
</ContextMenu>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContextMenu" Value="{StaticResource PageContextMenu}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate >
<Border  BorderThickness="2" BorderBrush="White" HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Stretch">
<Label Content="{Binding PresentationName}"/>
<Expander  VerticalAlignment="Top" HorizontalAlignment="Stretch">
<Expander.Header>
<Label Content="{Binding FrameStatusText}"/>
</Expander.Header>
<ListBox Name="FrameListBox" ItemsSource="{Binding Frames}" HorizontalAlignment="Stretch" SelectionMode="Extended">
<ListBox.Resources>
<ContextMenu x:Key="FrameContextMenu">
<MenuItem Header="_Add Frame" Name="ContextAddFrame"/>
<MenuItem Header="_Edit Frame" Name="ContextEditFrame"/>
<MenuItem Header="_Delete Selected Frame(s)" Name="ContextDeleteFrames" Click="ContextDeleteFrames_Click"/>
<MenuItem Header="Show _Preview" Name="ContextShowPreview" Click="ContextShowPreview_Click"/>
</ContextMenu>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContextMenu" Value="{StaticResource FrameContextMenu}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding PresentationName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>

代码隐藏:

private void ContextDeletePage_Click(object sender, RoutedEventArgs e)
{ //this works
Workspace.Content.DeleteSelectedPages();
}
private void ContextDeleteFrames_Click(object sender, RoutedEventArgs e)
{ //this doesn't!
Workspace.Content.DeleteSelectedFrames();
}

不要在DataTemplate中使用事件。他们不会工作。

将第二个上下文菜单从DataTemplate的资源移动到PageListBox资源中,如下所示:

<ListBox Name="PageListBox">
<ListBox.Resources>
<!-- ... other resources... -->
<ContextMenu x:Key="FrameContextMenu">
<MenuItem Header="_Add Frame" Name="ContextAddFrame"/>
<MenuItem Header="_Edit Frame" Name="ContextEditFrame"/>
<MenuItem Header="_Delete Selected Frame(s)" Click="ContextDeleteFrames_Click"/>
<MenuItem Header="Show _Preview" Name="ContextShowPreview" Click="ContextShowPreview_Click"/>
</ContextMenu>
</ListBox.Resources>
</ListBox>

。或使用命令而不是事件:

<MenuItem Header="_Delete Selected Frame(s)" Command="{Binding DeleteFrameCommand}"/>

其中DeleteFrameCommand是类型ICommandRoutedCommand的属性。

如果要使用命令,则应注意上下文菜单不在其PlacementTarget的可视化树中,因此必须使用一些帮助程序来使绑定工作(绑定代理或PlacementTarget.Tag属性等)。

最新更新