2009-01-18 4 views
1

J'ai le TabControl sur lequel je définis le ContextMenu.La façon correcte de trouver le TabItem à partir de la commande ContextMenu

Tous les éléments ContextMenu ont des commandes définies. Toutes les commandes sont routées et les commandes CommandBindings sont définies à plusieurs niveaux au-dessus du contrôle TabControl.

Donc la question est: dans les gestionnaires d'événements CommandExtraction CanExecute/Execute, quelle est la bonne façon de savoir sur quel TabItem le menu a été appelé? Par correct je veux dire celui qui ne serait pas cassé si je change quelque chose comme le modèle TabItem.

Ou peut-être l'approche globale est erronée et je ne devrais pas utiliser de commandes routées pour cela? J'ai initialement utilisé le routage pour la commande Ajouter un nouvel onglet qui nécessite des raccourcis clavier.

Merci d'avance.

MISE À JOUR:

solution d'Igor est plus propre de POV architecturale (sauf que je supprimerais _ dans ViewModel), mais je veux avoir une commande Fermer réutilisable qui est indépendante de ce que TabControl est lié à (depuis Fermer/Fermer Tout pour les onglets existent dans toutes sortes d'applications et ne sont pas sémantiquement liés à un modèle spécifique).

En outre, je ne peux pas utiliser DataTemplate personnalisé car j'ai déjà un modèle personnalisé, et le sous-classement rendrait la solution un peu trop compliquée.

Répondre

1

Il semble que j'ai trouvé la réponse moi-même, mais il est très unelegant:

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

J'ajouter le ContextMenu à TabItem au lieu de TabControl, et lier CommandTarget au TabItem.

Il est intéressant de savoir s'il existe une meilleure réponse.

1

Bien sûr, il y a une meilleure réponse. Vous devez travailler avec Model/ViewModel, pas d'affichage. Voici un exemple simplifié de mon code:

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

Voici le code qui gère cette commande.

Région « Fermer la 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 

Fin Région

Comme vous pouvez le voir, mon code n'ont pas besoin de savoir qui TabItem a été cliqué, juste besoin de savoir quel objet de données était lié à ce TabItem. En tout cas, si vous avez besoin de connaître TabItem, sur lequel vous avez cliqué, vous pouvez le trouver par objet de données qui y est lié en utilisant l'objet ContainerGenerator et votre datatemplate.

Avec mes meilleurs vœux de Russie!

+0

Merci, voir ma réponse à la fin de la question d'origine. Encore, +1. –

Questions connexes