Pregunta

OK, he descubierto la manera de conseguir mi rejilla de elementos de interfaz de usuario a ampliar, mediante el uso de LayoutTransform y ScaleTransform. Lo que no entiendo es cómo puedo conseguir mi punto de vista para responder a CTRL + MouseWheelUp \ Abajo para hacerlo, y cómo hacer que el código en el patrón MVVM.

Mi primera idea era guardar el ZOOMFACTOR como una propiedad, y se unen a un comando para ajustarlo.

Yo estaba mirando algo como:

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

pero veo 2 números:

1) Creo que no hay una manera de saber si la rueda se mueve hacia arriba o hacia abajo, ni puedo ver cómo determinar en qué medida. He visto MouseWheelEventArgs.Delta, pero no tienen idea de cómo llegar a él.

2) La unión a un comando en el modelo de vista no me parece bien, ya que es estrictamente un Ver cosa.

Desde el zoom es vista estrictamente interfaz de usuario única, estoy pensando que el código real debe ir en el código subyacente.

¿Cómo te chicos implementar esto?

p.s., Estoy usando .NET \ WPF 4.0 utilizando la cincha por un MVVM.

¿Fue útil?

Solución

Yo sugeriría que implemente un comando de zoom genérica en la máquina virtual. El comando se puede parametrizar con un nuevo nivel de zoom, o (tal vez incluso más simple) se podría implementar un IncreaseZoomCommand y DecreaseZoomCommand . A continuación, utilice el código de la vista detrás de llamar a estos comandos después de haber procesado los argumentos del evento del evento rueda del ratón. Si la diferencia es positiva, zoom, si el zoom negativo a cabo.

No hay ningún daño en la solución de este problema mediante el uso de unas pocas líneas de código subyacente. La idea principal de MVVM es que, usted es capaz de rastrear y modificar el estado de casi completa de la vista en un objeto que no depende de la interfaz de usuario (mejora la capacidad de prueba). En consecuencia, el cálculo de la nueva ventana que es el resultado del zoom se debe hacer en la máquina virtual y no en código detrás.

El pequeño hueco de la capacidad de prueba que existe en el código detrás puede o bien ser descartado o cubierta por las pruebas de interfaz de usuario automáticas. pruebas automáticas de interfaz de usuario, sin embargo, pueden ser muy costosos.

Otros consejos

la anwser real es para escribir su propia MouseGesture, que es fácil.

<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 no desea usar código subyacente puede utilizar la funcionalidad de la luz EventToCommand MVVM:

Ver:

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

modelo de vista:

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

Espero que esto ayude a alguien. Sé que la pregunta es un poco viejo ...

Creo que lo que su tratando de hacer es muy relacionada con la vista por lo que no hay ningún daño en poner el código en su código detrás (en mi opinión al menos), aunque estoy seguro de que hay maneras elegantes de la manipulación de este ejemplo que es más modelo de vista basado.

Usted debe ser capaz de registrar al evento OnPrevewMouseWheel, comprobar si el usuario tiene la clave de control presionada y cambiar el factor de zoom en forma apropiada para conseguir el efecto de enfoque que busca.

Estoy de acuerdo con las dos respuestas, y sólo añadiría que para usar código subyacente es la única forma en este caso, por lo que ni siquiera tiene que pensar en si se rompe cualquier buenas prácticas o no.

El hecho es que la única manera de conseguir los MouseEventArgs (y por lo tanto el Delta) está en el código detrás, así que coge lo que necesita allí (sin lógica necesaria para eso) y pasarlo a su modelo de vista como Olli sugerido.

Por otro lado es posible que desee utilizar un delta más genérico (por ejemplo, se divide por 120 antes de pasarlo como un paso para el modelo de vista) con el fin de mantenerlo ignorante de los convenios relacionados con la vista o el sistema operativo . Esto permitirá la máxima reutilización de su código en el modelo de vista.

Para evitar el problema, no es una opción más: -utilizar un ContentPresenter en el XAML y dejar que su contenido puede unir a un objeto modelo de vista. -Mango los eventos rueda del ratón en el modelo de vista.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top