2010-02-16 13 views
8

OK, ho capito come ottenere gli elementi della griglia della UI per lo zoom, utilizzando LayoutTransform e ScaleTransform. Quello che non capisco è come posso convincere la mia vista a rispondere a CTRL + MouseWheelUp \ Down per farlo e come adattare il codice al pattern MVVM.Mouse Accoppiamento della rotellina del mouse per ingrandire WPF e MVVM

La mia prima idea era quella di memorizzare lo ZoomFactor come proprietà e associarlo a un comando per regolarlo.

stavo guardando qualcosa di simile:

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

ma vedo 2 problemi:

1) Io non credo che ci sia un modo per dire se la ruota è stata spostata verso l'alto o verso il basso, né posso vedere come determinare di quanto. Ho visto MouseWheelEventArgs.Delta, ma non ho idea di come ottenerlo.

2) Il collegamento a un comando sul viewmodel non sembra corretto, in quanto è strettamente un oggetto View.

Poiché lo zoom è esclusivamente UI View only, sto pensando che il codice effettivo debba essere inserito nel code-behind.

Come vorreste implementarlo?

p.s., Sto usando .net \ wpf 4.0 utilizzando Cinch per MVVM.

+0

Trovato questo sul Web, può essere che può aiutare ... http://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application .aspx – dunamis

risposta

5

Suggerisco di implementare un comando di zoom generico nella VM. Il comando può essere parametrizzato con un nuovo livello di zoom o (forse anche più semplice) è possibile implementare un IncreaseZoomCommand e DecreaseZoomCommand. Quindi utilizzare il codice della vista per richiamare questi comandi dopo aver elaborato gli argomenti dell'evento della rotellina del mouse. Se il delta è positivo, ingrandisci, se si riduce lo zoom.

Non c'è alcun problema nel risolvere questo problema utilizzando alcune righe di codice. L'idea principale di MVVM è che sei in grado di tracciare e modificare quasi lo stato completo della tua vista in un oggetto che non dipende dall'interfaccia utente (migliora la testabilità). Di conseguenza, il calcolo della nuova finestra che è il risultato dello zoom dovrebbe essere fatto nella VM e non nel codice retrostante.

La piccola lacuna di testabilità esistente nel codice sottostante può essere ignorata o coperta dai test automatici dell'interfaccia utente. I test automatici dell'interfaccia utente, tuttavia, possono essere molto costosi.

0

Penso che il tuo tentativo di fare sia molto correlato alla vista quindi non c'è nulla di male nel mettere codice nel codice (almeno secondo me), anche se sono sicuro che ci sono modi eleganti per gestire questo in modo tale che sia più basato su viewmodel.

Dovresti essere in grado di registrarti all'evento OnPrevewMouseWheel, controllare se l'utente ha premuto il tasto di controllo e modificare il fattore di zoom di conseguenza per ottenere l'effetto di zoom che stai cercando.

0

Sono d'accordo con entrambe le risposte, e vorrei solo aggiungere che usare il codice dietro è l'unico modo in questo caso, quindi non devi nemmeno pensare se rompe qualche buona pratica o meno.

Il fatto è che l'unico modo per ottenere MouseEventArgs (e quindi il Delta) è nel codice, quindi prendi ciò che ti serve (non è necessaria alcuna logica) e passalo al modello di visualizzazione come olli suggerito.

Dall'altro lato, è possibile utilizzare un delta più generico (ad es. Dividerlo per 120 prima di passarlo come passaggio al modello di vista) per tenerlo all'oscuro di qualsiasi convenzione relativa alla vista o al OS. Ciò consentirà il massimo riutilizzo del codice nel modello di visualizzazione.

1

Se non si desidera utilizzare codice dietro è possibile utilizzare la funzionalità di luce EventToCommand MVVM:

Vista:

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

Spero che questo aiuta qualcuno. So che la domanda è un po 'vecchia ...

+0

Trovo strano che la tua VM abbia un evento indirizzato – Alan

8

il vero anser è quello di scrivere il proprio MouseGesture, che è facile.

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






public class MouseWheelGesture : MouseGesture 
    { 
    public WheelDirection Direction { get; set; } 


    public static MouseWheelGesture CtrlDown 
    { 
     get 
     { 
     return new MouseWheelGesture(ModifierKeys.Control) { Direction = WheelDirection.Down }; 
     } 
    } 


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

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



    public override bool Matches(object targetElement, InputEventArgs inputEventArgs) 
    { 
     if (!base.Matches(targetElement, inputEventArgs)) return false; 
     if (!(inputEventArgs is MouseWheelEventArgs)) return false; 
     var args = (MouseWheelEventArgs)inputEventArgs; 
     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, 
    } 

    } 
0

Per evitare tutto il problema, v'è un'opzione più: -use un ContentPresenter in XAML e lasciare che è contenuto essere associato a un oggetto ViewModel. - gestisce gli eventi della rotellina del mouse all'interno del modello di visualizzazione.

Problemi correlati