Question

OK, j'ai compris comment obtenir mon grille d'éléments de l'interface utilisateur pour zoomer, en utilisant LayoutTransform et ScaleTransform. Ce que je ne comprends pas comment je peux obtenir mon point de vue de répondre à CTRL + MouseWheelUp \ vers le bas pour le faire, et comment adapter le code dans le modèle MVVM.

Ma première idée était de stocker les ZOOMFACTOR comme une propriété, et se lier à une commande pour le régler.

Je cherchais quelque chose comme:

<UserControl.InputBindings>
 <MouseBinding Command="{Binding ZoomGrid}" Gesture="Control+WheelClick"/>
</UserControl.InputBindings>

mais je vois 2 questions:

1) Je ne pense pas qu'il y ait un moyen de dire si la roue a été déplacée vers le haut ou vers le bas, et je ne peux voir comment déterminer combien. Je l'ai vu MouseWheelEventArgs.Delta, mais ne sais pas comment l'obtenir.

2) La liaison à une commande sur le viewmodel ne semble pas juste, car il est strictement une chose vue.

Étant donné que le zoom est strictement UI View seulement, je pense que le code réel devrait aller dans le code-behind.

Comment cela vous les gars mettre en œuvre?

p.s., J'utilise .net \ WPF 4.0 en utilisant Cinch pour MVVM.

Était-ce utile?

La solution

Je suggère que vous mettre en œuvre une commande de zoom générique dans votre VM. La commande peut être paramétrés avec un nouveau niveau de zoom, ou (peut-être encore plus simple), vous pouvez mettre en place un IncreaseZoomCommand et DecreaseZoomCommand . Ensuite, utilisez le code de la vue derrière appeler ces commandes après avoir traité les arguments d'événement de l'événement Wheel Mouse. Si le delta est positif, zoom avant, si le zoom négatif sur.

Il n'y a pas de mal à résoudre ce problème en utilisant quelques lignes de code derrière. L'idée principale de MVVM est que, vous êtes en mesure de suivre et de modifier à peu près l'état complet de votre point de vue dans un objet qui ne dépend pas de l'interface utilisateur (améliore la testabilité). Par conséquent, le calcul de la nouvelle fenêtre qui est le résultat du zoom doit être fait dans la machine virtuelle et non dans le code derrière.

Le faible écart de testabilité qui existe dans le code sous-jacent peut être soit ignoré ou couvert par des tests de l'interface utilisateur automatique. Tests automatiques de l'interface utilisateur, cependant, peut être très coûteux.

Autres conseils

le vrai anwser est d'écrire votre propre MouseGesture, ce qui est facile.

<MouseBinding Gesture="{x:Static me:MouseWheelGesture.CtrlDown}"  
              Command="me:MainVM.SendBackwardCommand" />

public class MouseWheelGesture : MouseGesture
{
    public static MouseWheelGesture CtrlDown
        => new MouseWheelGesture(ModifierKeys.Control) { Direction = WheelDirection.Down


    public MouseWheelGesture(): base(MouseAction.WheelClick)
    {
    }

    public MouseWheelGesture(ModifierKeys modifiers) : base(MouseAction.WheelClick, modifiers)
    {
    }

    public WheelDirection Direction { get; set; }

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
    {
        if (!base.Matches(targetElement, inputEventArgs)) return false;
        if (!(inputEventArgs is MouseWheelEventArgs args)) return false;
        switch (Direction)
        {
            case WheelDirection.None:
                return args.Delta == 0;
            case WheelDirection.Up:
               return args.Delta > 0;
            case WheelDirection.Down:
                return args.Delta < 0;
            default:
                return false;
        }
    }



    public enum WheelDirection
    {
      None,
      Up,
      Down,
    }

}

Si vous ne voulez pas utiliser le code derrière vous pouvez utiliser la fonctionnalité EventToCommand de la lumière MVVM:

Voir:

 <...
     xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
     ...> 
<i:Interaction.Triggers>
         <i:EventTrigger EventName="PreviewMouseWheel">
             <cmd:EventToCommand Command="{Binding
     Path=DataContext.ZoomCommand,
     ElementName=Root, Mode=OneWay}"
         PassEventArgsToCommand="True"   />
         </i:EventTrigger> </i:Interaction.Triggers>

ViewModel:

ZoomCommand = new RelayCommand<RoutedEventArgs>(Zoom);
...
public void Zoom(RoutedEventArgs e)
{
    var originalEventArgs = e as MouseWheelEventArgs;
    // originalEventArgs.Delta contains the relevant value
}

J'espère que cela aide quelqu'un. Je sais que la question est un peu vieux ...

Je pense que vous essayez de faire est très liée à la vue donc il n'y a pas de mal à mettre le code dans votre code derrière (à mon avis au moins), même si je suis sûr qu'il ya des façons élégantes de la manipulation de ce tel qu'il est plus basé viewmodel.

Vous devriez pouvoir vous inscrire à l'événement OnPrevewMouseWheel, vérifier si l'utilisateur a obtenu la touche de commande enfoncée et changer votre facteur de zoom en fonction pour obtenir l'effet de zoom que vous recherchez.

Je suis d'accord avec les deux réponses, et je n'ajouter que d'utiliser le code est derrière la seule façon dans ce cas, vous ne même pas penser à si elle brise les bonnes pratiques ou non.

Le fait est, la seule façon de mettre la main sur les MouseEventArgs (et donc le delta) est dans le code derrière, donc prenez ce que vous avez besoin là-bas (pas de logique nécessaire pour cela) et passez à votre modèle de vue que olli suggéré.

Du côté de la médaille, vous pouvez utiliser un delta plus générique (par exemple diviser par 120 avant de passer comme une étape du modèle de vue) afin de le garder ignorant toutes les conventions relatives à la vue ou le système d'exploitation . Cela permettra une réutilisation maximale de votre code dans le modèle de vue.

Pour éviter le problème, il y a une option supplémentaire: -utiliser un ContentPresenter dans le XAML et laisser son contenu lié à un objet viewmodel. -Poignée les événements mouseWheel dans le viewmodel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top