2010-10-21 4 views
0

J'ai un contrôle à l'intérieur d'un canevas et je veux pouvoir le déplacer en utilisant les touches fléchées. Par souci d'essayer les choses, j'ai créé la classe suivante, qui fait ce que je veux.Attacher/lier le même ensemble de commandes à plusieurs contrôles

<Window x:Class="DiagramDesigner.CanvasControlArrowKeyTest" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="CanvasControlArrowKeyTest" Height="300" Width="300"> 
    <Canvas> 
     <Canvas.InputBindings> 
      <KeyBinding Key="Down" Command="MoveDown" /> 
      <KeyBinding Key="Up" Command="MoveUp" /> 
      <KeyBinding Key="Right" Command="MoveRight" /> 
      <KeyBinding Key="Left" Command="MoveLeft" /> 
     </Canvas.InputBindings> 
     <Button> 
      <Button.CommandBindings> 
       <CommandBinding Command="MoveDown" Executed="MoveDown_Executed" /> 
       <CommandBinding Command="MoveUp" Executed="MoveUp_Executed" /> 
       <CommandBinding Command="MoveLeft" Executed="MoveLeft_Executed" /> 
       <CommandBinding Command="MoveRight" Executed="MoveRight_Executed" /> 
      </Button.CommandBindings> 
     </Button> 
    </Canvas> 
</Window> 

Voici un extrait du code-behind:

private void MoveDown_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
    var uiElement = (UIElement)sender; 
    double value = Canvas.GetTop(uiElement); 
    value = Double.IsNaN(value) ? 0 : value; 
    value++; 
    Canvas.SetTop(uiElement, value < 0 ? 0 : value); 
} 

Tout cela fonctionne très bien, mais ce que je veux vraiment est un tas de boutons avec cette capacité, non seulement celui-là. Comment puis-je m'assurer que chaque bouton a ces CommandBindings? S'il y a un moyen plus simple que d'utiliser CommandBindings, qu'est-ce que cela pourrait être?

Mise à jour: Sur demande, voici une autre méthode qui ne semble pas fonctionner:

<Window x:Class="DiagramDesigner.CanvasControlArrowKeyTest" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="CanvasControlArrowKeyTest" Height="300" Width="300"> 
    <Window.CommandBindings> 
     <CommandBinding Command="MoveDown" Executed="MoveDown_Executed" /> 
     <CommandBinding Command="MoveUp" Executed="MoveUp_Executed" /> 
     <CommandBinding Command="MoveLeft" Executed="MoveLeft_Executed" /> 
     <CommandBinding Command="MoveRight" Executed="MoveRight_Executed" /> 
    </Window.CommandBindings> 
    <Window.InputBindings> 
     <KeyBinding Key="Down" Command="MoveDown" /> 
     <KeyBinding Key="Up" Command="MoveUp" /> 
     <KeyBinding Key="Right" Command="MoveRight" /> 
     <KeyBinding Key="Left" Command="MoveLeft" /> 
    </Window.InputBindings> 
    <Canvas > 
     <Button Width="50" Height="50" /> 
    </Canvas> 
</Window> 

C#

private void MoveDown_Executed(object sender, ExecutedRoutedEventArgs e) 
{ 
    var uiElement = (UIElement)e.OriginalSource; // Still doesn't point to the Button 
    double value = Canvas.GetTop(uiElement); 
    value = Double.IsNaN(value) ? 0 : value; 
    value++; 
    Canvas.SetTop(uiElement, value < 0 ? 0 : value); 
} 

Mise à jour: J'ai renoncé à cette approche. J'ai fini par utiliser un different solution pour le problème, un qui n'utilise pas de commandes.

Répondre

0

Vous devriez jeter un oeil à des gestionnaires d'événements routés: http://msdn.microsoft.com/en-us/library/ms742806.aspx

Le lien ci-dessus a un exemple de la façon de faire ce que vous demandez.

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1"> 
    <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler"> 
    <Button Name="YesButton" Width="Auto" >Yes</Button> 
    <Button Name="NoButton" Width="Auto" >No</Button> 
    <Button Name="CancelButton" Width="Auto" >Cancel</Button> 
    </StackPanel> 
</Border> 

Et le code

private void CommonClickHandler(object sender, RoutedEventArgs e) 
{ 
    FrameworkElement feSource = e.Source as FrameworkElement; 
    switch (feSource.Name) 
    { 
    case "YesButton": 
     // do something here ... 
     break; 
    case "NoButton": 
     // do something ... 
     break; 
    case "CancelButton": 
     // do something ... 
     break; 
    } 
    e.Handled=true; 
} 
+0

Cela semble prometteur, seulement il n'y a aucun événement pour les commandes que je utilise (c'est, Button a un événement Click, mais il n'y a pas Button.MoveUp, Button.MoveDown, etc.). Je vais devoir lire à ce sujet pour voir si je peux le faire fonctionner. – Pat

+0

Je suppose qu'un événement routé est vraiment la solution que je suis allé avec: http://stackoverflow.com/questions/3992278/move-a-control-inside-a-canvas-using-directional-keys/3998438#3998438 – Pat

0

Si vous créez les CommandBindings dans l'objet de niveau supérieur (fenêtre dans ce cas), vous seriez en mesure de les réutiliser pour les enfants de la fenêtre.

<Window x:Class="TesterApp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:data="clr-namespace:TesterApp" 
     x:Name="TheMainWindow" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
    </Window.Resources> 
    <Window.InputBindings> 
     <KeyBinding Key="A" Command="MoveDown" /> 
    </Window.InputBindings> 
    <Window.CommandBindings> 
     <CommandBinding Command="MoveDown" Executed="MoveDown_Executed" /> 
    </Window.CommandBindings> 
    <Grid> 
     <Button Height="30" Width="80" Content="Click" Command="MoveDown" /> 
    </Grid> 
</Window> 
+0

Le problème est que le «expéditeur» pour l'événement n'est pas le bouton lui-même, mais le contrôle de haut niveau avec CommandBinding. J'ai besoin d'une référence au bouton lui-même afin que je puisse le déplacer en utilisant Canvas.SetTop, etc. – Pat

+0

vérifier la propriété OriginalSource du paramètre ExecutedRoutedEventArgs. – mdm20

+0

Oh, si seulement cela fonctionnait! Pour l'OriginalSource, je reçois toujours le Canvas (qui est où j'ai défini les commandes et les Input-Bindings) au lieu du bouton. – Pat

Questions connexes