1

我有我在其上设置 ContextMenu 的 TabControl。

所有 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 中删除 _),但我希望有一个独立于 TabControl 绑定的可重用关闭命令(因为所有类型的应用程序中都存在选项卡的关闭/关闭全部)并且没有在语义上链接到特定模型)。

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

4

2 回答 2

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。

有趣的是是否有更好的答案。

于 2009-01-18T22:08:59.967 回答
1

当然,还有更好的答案。您需要使用模型/视图模型,而不是视图。这是我的代码中的简化示例:

        <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>

这是处理此命令的代码。

    #Region "Close Page"

    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

    #End Region         

As you can see, my code don't have need to know which TabItem was clicked, just need to know which data object was bound to this TabItem. In anyway, if you need to know TabItem, which was clicked you can find it by Data object bounded to it using ContainerGenerator object and your datatemplate.

With best wishes from Russia!

于 2009-02-06T03:25:00.537 回答