質問

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の上のいくつかのレベルで定義されます。

質問は次のとおりです。CommandBindingCanExecute / Executeイベントハンドラーで、メニューが呼び出されたTabItemを見つける正しい方法は何ですか?正確には、TabItemテンプレートのようなものを変更しても壊れないものを意味します。

またはアプローチ全体が間違っている可能性があり、これにルーティングされたコマンドを使用しないでください?元々、ホットキーが必要な[新しいタブを追加]コマンドにルーティングを使用していました。

事前に感謝します。

更新

Igorのソリューションは、アーキテクチャPOVからはよりクリーンです(ViewModelで_を削除することを除く)が、TabControlがバインドされているものとは独立した再利用可能なCloseコマンドが必要です(すべてのタブにClose / Close Allが存在するため種類のアプリケーションであり、特定のモデルに意味的にリンクされていません。

また、カスタムテンプレートが既にあるため、カスタムDataTemplateを使用できません。サブクラス化すると、ソリューションが少し複雑になります。

役に立ちましたか?

解決

自分で答えを見つけたようですが、非常に違法です:

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

だから、ContextControlをTabControlではなくTabItemに追加し、CommandTargetをTabItemにバインドします。

より良い答えがあるかどうかは興味深いです。

他のヒント

もちろん、より良い答えがあります。ビューではなく、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>

このコマンドを処理するコードを次に示します。

地域<!> quot;ページを閉じる<!> quot;

    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オブジェクトで見つけることができます。

ロシアからの最高の願いを込めて!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top