从ContextMenu命令中找到TabItem的正确方法

时间:2009-01-18 11:00:22

标签: wpf tabcontrol contextmenu

我有TabControl,我正在设置ContextMenu。

所有ContextMenu元素都设置了命令。

<ContextMenu x:Key="tabMenu">
  <MenuItem Command="{x:Static tabs:TabCommands.Close}" />
  <MenuItem Command="{x:Static tabs:TabCommands.CloseAllButThis}" />
  <MenuItem Command="{x:Static tabs:TabCommands.CloseAll}" />
</ContextMenu>

所有命令都被路由,并且CommandBindings被定义在TabControl之上的几个级别。

所以问题是:在CommandBinding CanExecute / Execute事件处理程序中,找出调用菜单的TabItem的正确方法是什么?正确的意思是指如果我改变像TabItem模板那样不会破坏的那个。

或者整个方法可能是错误的,我不应该使用路由命令?我最初使用路由添加新标签命令,这需要热键。

提前致谢。

更新

Igor的解决方案来自架构POV更清晰(除了我会在ViewModel中删除_),但我希望有一个可重用的Close命令,它独立于TabControl的绑定(因为所有选项卡都有关闭/关闭所有)各种应用程序,并且没有语义链接到特定模型。)

另外,我不能使用自定义DataTemplate,因为我已经有了一个自定义模板,并且对它进行子类化会使解决方案过于复杂。

2 个答案:

答案 0 :(得分:1)

似乎我自己找到了答案,但它非常不优雅:

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

<Style TargetType="TabItem">
  <Setter Property="ContextMenu" Value="{StaticResource tabMenu}" />
</Style>

所以我将ContextMenu添加到TabItem而不是TabControl,并将CommandTarget绑定到TabItem。

是否有更好的答案很有意思。

答案 1 :(得分:1)

当然,有一个更好的答案。您需要使用Model / ViewModel,而不是查看。这是我的代码中简化的例子:

        <TabControl Margin="3" Grid.Column="1" Name="tbPages"
                    ItemsSource="{Binding DsmProject.Pages}" 
                    ItemTemplate="{DynamicResource TabItemTemplate}"
                    IsSynchronizedWithCurrentItem="True">
        </TabControl>
<DataTemplate x:Key="TabItemTemplate">
    <StackPanel Orientation="Horizontal" ContextMenu="{DynamicResource cmPages}">
        <ContentPresenter Content="{Binding Path=Name}"/>
    </StackPanel>
</DataTemplate>
<ContextMenu x:Key="cmPages">
    <MenuItem Header="Close" Command="cmd:DSM2100Commands.ClosePage" CommandParameter="{Binding}" />
</ContextMenu>

以下是处理此命令的代码。

区域“关闭页面”

    Private Sub ClosePageCmd(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
        ViewModel_.History.TakeCommmand(New cmdRemovePage(ViewModel_, e.Parameter))
    End Sub

    Private Sub CanClosePageCmd(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
        e.CanExecute = ViewModel_.DsmProject IsNot Nothing AndAlso ViewModel_.DsmProject.Pages.Count > 1
    End Sub

结束地区

如您所见,我的代码不需要知道单击了哪个TabItem,只需要知道哪个数据对象绑定到此TabItem。无论如何,如果你需要知道TabItem,它被点击了你可以通过使用ContainerGenerator对象和你的datatemplate绑定到它的Data对象找到它。

带着俄罗斯的祝福!