2010-04-18 8 views
18

Je crée une application WPF à l'aide du modèle de conception MVVM et j'essaie d'étendre le contrôle TabItem pour qu'il ferme l'onglet lorsque l'utilisateur clique sur le bouton central de la souris. J'essaye de réaliser ceci en utilisant InputBindings, et cela fonctionne très bien jusqu'à ce que j'essaye de le définir dans un style. J'ai appris que vous ne pouvez pas ajouter des InputBindings à un style sauf si vous l'attachez à l'aide d'un DependencyProperty. J'ai donc suivi ce post similaire here... et ça marche ... presque. Je peux fermer un onglet en utilisant le bouton du milieu de la souris, mais cela ne fonctionnera pas sur les autres onglets (tous les onglets sont ajoutés à l'exécution et héritent du même style).Définition de InputBindings dans un style

J'ai donc besoin d'aide. Pourquoi cela fonctionnerait-il seulement la première fois, et pas après? Évidemment, je pourrais créer un contrôle personnalisé qui hérite d'un TabItem et le faire fonctionner, mais je voudrais comprendre cela car je peux voir cela être étendu dans mes projets. Je ne suis pas un expert sur DependencyProperties, alors s'il vous plaît aidez-moi. Merci!

Style:

<Style TargetType="{x:Type TabItem}"> 
    <Setter Property="w:Attach.InputBindings"> 
     <Setter.Value> 
      <InputBindingCollection> 
       <MouseBinding MouseAction="MiddleClick" 
           Command="{Binding CloseCommand}"/> 
      </InputBindingCollection> 
     </Setter.Value> 
    </Setter> 
    ... 
</Style> 

Classe

public class Attach 
{ 
    public static readonly DependencyProperty InputBindingsProperty = 
     DependencyProperty.RegisterAttached("InputBindings", typeof(InputBindingCollection), typeof(Attach), 
     new FrameworkPropertyMetadata(new InputBindingCollection(), 
     (sender, e) => 
     { 
      var element = sender as UIElement; 
      if (element == null) return; 
      element.InputBindings.Clear(); 
      element.InputBindings.AddRange((InputBindingCollection)e.NewValue); 
     })); 

    public static InputBindingCollection GetInputBindings(UIElement element) 
    { 
     return (InputBindingCollection)element.GetValue(InputBindingsProperty); 
    } 

    public static void SetInputBindings(UIElement element, InputBindingCollection inputBindings) 
    { 
     element.SetValue(InputBindingsProperty, inputBindings); 
    } 
} 
+0

J'ai rencontré le problème exact décrit ci-dessus même avec le code suggéré par Daniel. Il semble qu'il y ait quelque chose de très étrange lorsqu'on utilise la classe Attach ci-dessus, surtout dans un style. J'ai trouvé que DataContext était null "parfois" quand les InputBindings ont été ajoutés, ainsi quand la liaison s'est produite il ne pourrait pas localiser les commandes. Je n'ai jamais trouvé de solution mais j'ai fini par dupliquer les liaisons comme dans la réponse ci-dessous. – Asheh

Répondre

14

Peu importe, je pensais que ce moi-même. J'ai fini par ne même pas utiliser la classe Attach ci-dessus ... à la place j'ai utilisé InputBindings sur le ControlTemplate pour le TabItem (qui est une bordure), donc ça ressemblait à ça ... Je ne sais pas pourquoi je ne pensais pas de cela en premier lieu .. :)

<ControlTemplate TargetType="{x:Type TabItem}"> 
    <Grid SnapsToDevicePixels="true"> 
     <Border x:Name="Bd" ...> 
      <DockPanel> 
       ... 
      </DockPanel> 
      <Border.InputBindings> 
       <MouseBinding MouseAction="MiddleClick" 
           Command="{Binding CloseCommand}"/> 
      </Border.InputBindings> 
     </Border> 
    </Grid> 
    ... 
</ControlTemplate> 
+0

Je n'aime pas cette solution car je dois redéfinir n'importe quel Template que j'ai créé ... –

14

Votre classe "Attach" a bien fonctionné pour moi! Si quelqu'un a besoin, l'astuce est de style utilisé comme celui-ci, avec le x: modificateur partagé:

<InputBindingCollection x:Key="inputCollection" x:Shared="False"> 
     <KeyBinding Key="Del" Command="{Binding DeleteItemCommand}"/> 
</InputBindingCollection> 

<Style TargetType="{x:Type TabItem}"> 
    <Setter Property="w:Attach.InputBindings" Value="{StaticResource inputCollection}" /> 
    ... 
</Style> 

Merci!

Questions connexes