WPF 上下文菜单 Click 事件在一个地方有效,在另一个地方无效
WPF Context Menu Click event works in one place, not in another
我有以下 XAML 生成一个列表框,其中每个项目都在扩展器中包含另一个列表框,并且我已将 PageContextMenu
定义为顶级列表的上下文菜单,并且 FrameContextMenu
用于较低级别的列表。
问题:两者都显示正确,但点击事件只在顶层上下文菜单上起作用,而不在下层上下文菜单上起作用。例如,单击 PageContextMenu
中的 Delete Selected
会正确调用关联的处理程序,但单击 FrameContextMenu
中的 Delete Selected Frame(s)
不会触发关联的处理程序。我没有看到任何错误指示,即使我在 ContextDeleteFrames_Click
中放置了一个断点,它也不会被击中。好像根本没有与该菜单项关联的处理程序。
我已经查看了许多与上下文菜单不起作用相关的其他问题,但 none 似乎适用。是不是两个列表框嵌套有问题?
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
是 ICommand
或 RoutedCommand
类型的 属性。
如果你想使用命令,你应该知道上下文菜单不在其 PlacementTarget
的可视化树中,所以你必须使用一些帮助程序来使绑定工作(a绑定代理或 PlacementTarget.Tag
属性 等)
我有以下 XAML 生成一个列表框,其中每个项目都在扩展器中包含另一个列表框,并且我已将 PageContextMenu
定义为顶级列表的上下文菜单,并且 FrameContextMenu
用于较低级别的列表。
问题:两者都显示正确,但点击事件只在顶层上下文菜单上起作用,而不在下层上下文菜单上起作用。例如,单击 PageContextMenu
中的 Delete Selected
会正确调用关联的处理程序,但单击 FrameContextMenu
中的 Delete Selected Frame(s)
不会触发关联的处理程序。我没有看到任何错误指示,即使我在 ContextDeleteFrames_Click
中放置了一个断点,它也不会被击中。好像根本没有与该菜单项关联的处理程序。
我已经查看了许多与上下文菜单不起作用相关的其他问题,但 none 似乎适用。是不是两个列表框嵌套有问题?
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
是 ICommand
或 RoutedCommand
类型的 属性。
如果你想使用命令,你应该知道上下文菜单不在其 PlacementTarget
的可视化树中,所以你必须使用一些帮助程序来使绑定工作(a绑定代理或 PlacementTarget.Tag
属性 等)