2009-09-05 7 views
2

L'une des choses que j'aime vraiment avec WPF est la mesure dans laquelle mes vues peuvent être construites de manière déclarative, c'est-à-dire. utilisant XAML plutôt que le code-behind.WPF: CommandParameters pour les liaisons d'entrée

Maintenant, je suis vraiment perplexe par InputBindings, parce que leurs CommandParameters n'acceptent pas les liaisons. J'imagine que mon cas est assez générique et simple, mais je ne vois pas comment je peux le faire sans avoir recours au code-behind. Considérez:

<ListBox Name="casingsListBox" ItemsSource="{Binding Path=Casings}" SelectedValuePath="Id"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path=Title}"/> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
    <ListBox.InputBindings> 
     <!-- Doesn't work: --> 
     <MouseBinding Gesture="LeftDoubleClick" 
         Command="ApplicationCommands.Open" 
         CommandParameter="{Binding RelativeSource={RelativeSource Self} Path=SelectedValue}"/> 
    </ListBox.InputBindings> 
</ListBox> 

Cela ne fonctionnera pas, car l'expression de liaison pour CommandParameter du MouseBinding est illégale.

Je me demande: quel est le point d'ajouter un geste de clic de souris à une zone de liste si je ne peux pas accéder à la valeur sélectionnée? Cela peut être facilement résolu à l'aide d'un gestionnaire d'événements code-behind, bien sûr, ou en demandant à la commande consumer d'extraire l'id de la source de commande, mais il y a plusieurs raisons pour lesquelles cela n'est pas souhaitable. Mis à part le fait que des tas de code code-behind vaincre (en partie) le but de WPF en premier lieu, cela rend les concepteurs d'interface utilisateur travaillant dans Expression Blend moins habilités. Et bon sang, mon paramètre de commande doit être un ID, pas un élément de l'interface utilisateur !! Subjectif: Après avoir navigué pendant un certain temps, je suis frappé par la quantité de code que je vois dans les questions liées à WPF. J'ai l'impression que les développeurs s'en tiennent à nos vieilles habitudes et se contentent de pirater le fichier code-behind plutôt que d'essayer d'utiliser la nouvelle version de l'interface utilisateur que WPF est supposé représenter. Qu'est-ce que tu penses?

Mais plus important encore: Quelqu'un peut-il me montrer une solution de contournement sans code pour ce problème apparemment trivial? De préférence sans terribles hacks comme this one.

+0

Je viens de trébucher sur ce problème, et je suis encore insatisfait des solutions que j'ai trouvées. Je vais commencer une petite prime et voir si quelque chose a changé depuis 2009 =) – Jens

Répondre

3

J'ai écrit un markup extension qui permet à DataBound de Command un InputBinding:

<KeyBinding Modifiers="Control" Key="E" Command="{input:CommandBinding EditCommand}"/> 

Votre situation est légèrement différente puisque vous voulez lier le CommandParameter, mais vous pouvez probablement adapter mon code pour l'adapter à votre cas . Notez que ce code utilise la réflexion privée, qui ne fonctionne qu'en confiance totale, et peut être cassée dans les versions ultérieures de WPF (en fait est cassé dans WPF 4.0 ... Je peux poster une version modifiée si vous en avez besoin).

Une autre option consiste à utiliser la classe CommandReference qui se trouve dans le MVVM toolkit:

<Window.Resources> 
    <c:CommandReference x:Key="EditCommandReference" Command="{Binding EditCommand}"/> 
</Window.Resources> 

... 

<KeyBinding Modifiers="Control" Key="E" Command="{StaticResource EditCommandReference}"/> 

Encore une fois, cela est pour lier la propriété Command, mais peut probablement être adapté pour lier le CommandParameter ...

1

La nouvelle façon de résoudre ce problème consiste à utiliser Expression Triggers/Actions qui vous permet de définir des raccourcis clavier sur des contrôles arbitraires effectuant des actions personnalisées (par exemple, l'exécution d'une commande).

Questions connexes