Frage

OK, ich habe herausgefunden, wie mein Grid von UI-Elementen erhalten, um zoomen von Layout und Scaletransform verwenden. Was ich nicht verstehe, ist, wie ich meine Ansicht zu reagieren auf STRG + MouseWheelUp \ nach unten, es zu tun bekommen kann, und wie Sie den Code in das MVVM Muster passen.

Meine erste Idee war es, den Zoomfactor als Eigenschaft zu speichern, und binden an einen Befehl, um es anzupassen.

Ich war auf der Suche auf so etwas wie:

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

aber ich sehe zwei Probleme:

1) Ich glaube nicht, gibt es eine Möglichkeit zu sagen, ob das Rad wurde nach oben oder unten, noch kann ich sehen, wie wie viel zu bestimmen. Ich habe MouseWheelEventArgs.Delta gesehen, aber keine Ahnung, wie es zu bekommen.

2) Bindung an einen Befehl auf dem Viewmodel scheint nicht richtig, da es eine reine Ansicht Sache.

Da der Zoom ist streng nur UI-Ansicht, ich denke, dass der eigentliche Code in dem Code-Behind gehen sollte.

Wie würden ihr dies umsetzen?

P. S., Ich verwende .net \ WPF 4.0 mit Cinch für MVVM.

War es hilfreich?

Lösung

Ich würde vorschlagen, dass Sie einen allgemeinen Zoom-Befehl in Ihrer VM implementieren. Der Befehl kann mit einem neuen Zoomstufe parametriert werden, oder (vielleicht sogar einfacher) können Sie einen IncreaseZoomCommand und DecreaseZoomCommand implementieren. Dann wird der Code der Ansicht verwenden, hinter diese Befehle aufzurufen, nachdem Sie die Ereignisargumente des Mausrads Ereignis verarbeitet haben. Wenn das Delta-positiv ist, vergrößert, wenn sie negativ verkleinern.

Es gibt keinen Schaden, dieses Problem zu lösen, indem Sie ein paar Zeilen Code hinter verwenden. Die Grundidee von MVVM ist, dass Sie sind in der Lage zu verfolgen und fast den kompletten Zustand Ihrer Ansicht in einem Objekt zu ändern, die nicht auf der Benutzeroberfläche abhängt (die Testbarkeit verbessert). In der Folge, die die Berechnung des neuen Ansichtsfensters das Ergebnis des Zooms ist, sollte in der VM und nicht im Code hinter erfolgen.

Der kleine Spalt der Testbarkeit, die entweder in dem Code-behind vorhanden ist, kann durch die automatischen UI Tests außer Acht gelassen oder abgedeckt werden. Automatische UI-Tests können jedoch sehr teuer sein.

Andere Tipps

das eigentliche anwser ist Ihre eigenen MouseGesture zu schreiben, die einfach ist.

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

}

Wenn Sie nicht wollen, Code verwenden, hinter Ihnen die EventToCommand Funktionalität von mvvm Licht verwenden können:

Ausblick:

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

Ansichtsmodell:

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

Ich hoffe, das jemand hilft. Ich weiß, die Frage ist etwas alt ...

Ich denke, was Ihr versucht zu tun ist sehr viel in Bezug auf die Ansicht, so gibt es keinen Schaden Code im Code hinter (meiner Meinung nach zumindest) bei der Umsetzung, obwohl ich sicher bin, gibt es elegante Möglichkeiten der Umgang mit diesem so dass es mehr Ansichtsmodell basiert.

Es soll möglich sein, auf die OnPrevewMouseWheel Veranstaltung anmelden, prüfen Sie, ob der Benutzer die Steuertaste gedrückt bekommen hat und Ihren Zoomfaktor ändern entsprechend den Zoom-Effekt Sie suchen zu erhalten.

Ich bin einverstanden mit beiden Antworten und würde nur hinzufügen, dass die Verwendung Code zurück ist der einzige Weg, in diesem Fall, so dass Sie gar nicht erst darüber nachdenken, ob es irgendwelche guten Praktiken bricht oder nicht.

Fakt ist, der einzige Weg, halten die MouseEventArgs zu bekommen (und damit das Delta) in der Code-behind, so greifen, was Sie brauchen dort (keine Logik dafür erforderlich) und geben sie nicht an Ihrer Ansicht nach Modell als olli vorgeschlagen.

Auf der anderen Seite können Sie eine generische Delta verwenden möchten (zB teilen sie durch 120, bevor Sie es als einen Schritt in die View-Modell übergeben), um es zu halten nichts von irgendwelchen der Ansicht bezogenen Konventionen oder der OS . Dies wird für eine maximale Wiederverwendung von Code in dem View-Modell ermöglichen.

das ganze Problem zu vermeiden, gibt es eine weitere Option: -Verwenden Sie einen Content in der XAML und lassen Sie es den Inhalt zu einem Viewmodel-Objekt gebunden werden. -handle die Mausrad Ereignisse im Ansichtsmodell.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top