Domanda

OK, ho capito come ottenere il mio griglia di elementi dell'interfaccia utente per lo zoom, utilizzando LayoutTransform e ScaleTransform. Quello che non capisco è come posso ottenere la mia vista di rispondere a CTRL + MouseWheelUp \ Giù per farlo, e come adattare il codice nel modello MVVM.

La mia prima idea era quella di memorizzare lo zoomFactor come una proprietà, e si legano ad un comando per regolarlo.

stavo guardando qualcosa di simile a:

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

ma vedo 2 problemi:

1) Non credo che ci sia un modo per capire se la ruota è stata spostata verso l'alto o verso il basso, e non riesco a vedere come determinare di quanto. Ho visto MouseWheelEventArgs.Delta, ma non hanno alcuna idea di come farlo.

2) Il legame con un comando sul ViewModel non mi sembra giusto, in quanto è strettamente una vista cosa.

Dal momento che lo zoom è strettamente UI View solo, sto pensando che il codice vero e proprio dovrebbe andare nel code-behind.

Come ti ragazzi implementare questo?

P.S., Sto usando .net \ WPF 4.0 utilizzando Cinch per MVVM.

È stato utile?

Soluzione

Vorrei suggerire che si implementa un comando di zoom generico nel vostro VM. Il comando può essere parametrizzata con un nuovo livello di zoom, o (forse ancora più semplice) si potrebbe implementare un IncreaseZoomCommand e DecreaseZoomCommand . Quindi utilizzare il codice della vista dietro di chiamare questi comandi dopo aver elaborato gli argomenti degli eventi della manifestazione rotellina del mouse. Se il delta è positivo, lo zoom in, zoom se negativo fuori.

Non c'è nulla di male nel risolvere questo problema utilizzando poche righe di codice dietro. L'idea principale di MVVM è che, si è in grado di monitorare e modificare quasi lo stato completo della visualizzazione in un oggetto che non dipende l'interfaccia utente (migliora la testability). Di conseguenza, il calcolo della nuova finestra che è il risultato dello zoom dovrebbe essere fatto nella VM e non in codice dietro.

Il piccolo spazio di controllabilità che esiste nel codice dietro può o essere ignorata o coperto da test automatici UI. test automatici dell'interfaccia utente, tuttavia, può essere molto costoso.

Altri suggerimenti

la vera anwser è quello di scrivere il proprio MouseGesture, che è 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,
    }

}

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

Visualizza:

 <...
     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 questione è una specie di vecchio ...

Credo che ciò che il vostro cercando di fare è molto legato alla vista quindi non c'è nulla di male nel mettere codice nel tuo codice dietro (a mio parere, almeno), anche se sono sicuro che ci sono modi eleganti di manipolazione di questo esempio che è più ViewModel base.

Si dovrebbe essere in grado di registrarsi per l'evento OnPrevewMouseWheel, controllare se l'utente ha premuto il tasto di controllo e cambiare il tuo fattore di zoom di conseguenza per ottenere l'effetto di zoom che si sta cercando.

Sono d'accordo con entrambe le risposte, e sarebbe solo aggiungere che per utilizzare il codice è dietro l'unico modo in questo caso, in modo che non hanno nemmeno bisogno di pensare se si rompe eventuali buone pratiche o meno.

Il fatto è che l'unico modo per entrare in possesso dei MouseEventArgs (e quindi il Delta) è nel codice dietro, in modo da afferrare ciò che non ci serve (nessuna logica necessaria per questo) e passarlo al vostro modello di visualizzazione come olli suggerito.

Il rovescio della medaglia si consiglia di utilizzare un delta più generico (ad esempio, dividerlo per 120 prima di passare come un passo per il modello di vista) al fine di tenerlo all'oscuro di eventuali convenzioni relative alla vista o il sistema operativo . Ciò consentirà per il massimo riutilizzo del codice nel modello di visualizzazione.

Per evitare l'intero problema, v'è un'opzione più: -utilizzare un ContentPresenter in XAML e lasciare che è contenuto essere associato a un oggetto ViewModel. -Maniglia gli eventi rotellina del mouse all'interno del ViewModel.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top