2017-09-26 6 views
0
<utils:ScrollViewer x:Name="ImageViewer" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Row="2"                 
             CurrentHorizontalOffset="{Binding ScrollHorizontalValue, Mode=TwoWay}" 
             CurrentVerticalOffset="{Binding ScrollVerticalValue, Mode=TwoWay}"           
             > 
        <i:Interaction.Triggers> 
         <i:EventTrigger EventName="PreviewMouseWheel"> 
          <cmd:EventToCommand Command="{Binding MouseWheelZoomCommand}" PassEventArgsToCommand="True"/> 
         </i:EventTrigger> 
         <i:EventTrigger EventName="ScrollChanged"> 
          <cmd:EventToCommand Command="{Binding ScrollChangedCommand}" PassEventArgsToCommand="True"/> 
         </i:EventTrigger> 
        </i:Interaction.Triggers> 
        <Grid Background="{StaticResource ThatchBackground}" RenderTransformOrigin="0.5,0.5"> 
         <ItemsControl ItemsSource="{Binding CanvasItems}" ItemTemplate="{StaticResource templateOfROI}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <Canvas x:Name="BackPanel" 
             Width="{Binding DataContext.ImageWidth, ElementName=MainGrid}" 
             Height="{Binding DataContext.ImageHeight, ElementName=MainGrid}" 
             ClipToBounds="True"> 
             <Canvas.Background> 
              <ImageBrush x:Name="BackImage" 
                 ImageSource="{Binding DataContext.SelectedImage.Path, ElementName=MainGrid}"/> 
             </Canvas.Background> 

             <i:Interaction.Triggers> 
              <i:EventTrigger EventName="MouseRightButtonDown"> 
               <cmd:EventToCommand Command="{Binding DataContext.MouseRightCommand, ElementName=MainGrid}"/> 
              </i:EventTrigger> 
              <i:EventTrigger EventName="MouseLeftButtonDown"> 
               <cmd:EventToCommand Command="{Binding DataContext.MouseMoveStartCommand, ElementName=MainGrid}" PassEventArgsToCommand="True"/> 
              </i:EventTrigger> 
              <i:EventTrigger EventName="MouseMove"> 
               <cmd:EventToCommand Command="{Binding DataContext.MouseMovingCommand, ElementName=MainGrid}" PassEventArgsToCommand="True"/> 
              </i:EventTrigger> 
              <i:EventTrigger EventName="MouseRightButtonUp"> 
               <cmd:EventToCommand Command="{Binding DataContext.MouseMoveEndCommand, ElementName=MainGrid}"/> 
              </i:EventTrigger> 
              <i:EventTrigger EventName="MouseLeave"> 
               <cmd:EventToCommand Command="{Binding DataContext.MouseLeaveCommand, ElementName=MainGrid}"/> 
              </i:EventTrigger> 
             </i:Interaction.Triggers> 

             <Canvas.LayoutTransform> 
              <TransformGroup> 
               <ScaleTransform ScaleX="{Binding ScaleX}" 
                   ScaleY="{Binding ScaleY}"> 
               </ScaleTransform> 
             </TransformGroup> 
            </Canvas.LayoutTransform> 
           </Canvas> 
          </ItemsPanelTemplate> 
         </ItemsControl.ItemsPanel> 
        </ItemsControl> 
       </Grid> 
      </utils:ScrollViewer> 

Le point de référence est fixé avec les points Gauche et Dessus pour agrandir le canevas. Je voudrais zoomer et dézoomer sur le pointeur de la souris. Comment puis-je le faire dans le modèle MVVM? (Pas derrière le code). En utilisant la molette de la souris, je peux zoomer sur la toile. J'utilise déjà RenderTransformOrigin, CenterX, CenterY mais cela ne fonctionne pas. Je pense que j'ai fait une mauvaise approche. S'il vous plaît aidez-moi ..WPF Zoom Canvas Center sur la position de la souris

+1

Où est votre code qui gère le zoom? Même lorsque cela ne fonctionne pas comme prévu, vous devez toujours l'inclure dans votre approche actuelle. – grek40

Répondre

3

Puisque vous n'avez pas fourni votre code de zooming en cours, voici un exemple générique de zoom sur la position de la souris:

<Grid x:Name="grid1" Background="White" MouseWheel="Grid_MouseWheel"> 
    <Grid x:Name="grid2"> 
     <Grid.RenderTransform> 
      <MatrixTransform/> 
     </Grid.RenderTransform> 
     <Rectangle Width="20" Height="20" Margin="20" VerticalAlignment="Top" HorizontalAlignment="Left" Fill="Green"/> 
    </Grid> 
</Grid> 

Avec le code qui met à jour la matrice de transformation:

private void Grid_MouseWheel(object sender, MouseWheelEventArgs e) 
{ 
    var matTrans = grid2.RenderTransform as MatrixTransform; 
    var pos1 = e.GetPosition(grid1); 

    var scale = e.Delta > 0 ? 1.1 : 1/1.1; 

    var mat = matTrans.Matrix; 
    mat.ScaleAt(scale, scale, pos1.X, pos1.Y); 
    matTrans.Matrix = mat; 
    e.Handled = true; 
} 
+1

J'espère que cela ne vous dérange pas, mais j'ai ajouté une réponse, basée sur votre code, sous la forme d'un «comportement» pour les personnes essayant de s'en tenir au modèle MVVM. –

+0

@BradleyUffner Ça ne me dérange pas du tout. Une variété de bonnes solutions aide SO dans son ensemble et je suis plus que satisfait de la façon dont vous avez mentionné ma contribution;) – grek40

3

J'ai pris le code de @ Grek40 et l'ai converti en Behavior pour quiconque essayait de s'en tenir au modèle MVVM. Si vous votez pour cela, n'oubliez pas de voter également sa réponse, car la mienne est basée sur son travail. Il nécessite le paquet System.Windows.Interactivity.WPF nuget (ou un autre cadre) pour la classe de base Behavior. Vous pouvez l'appliquer à n'importe quel UIElement. Il ajoutera automatiquement le MatrixTransform pour vous, donc vous n'avez pas à le faire en XAML (il écrase toute transformation existante).

public class ZoomOnMouseWheel : Behavior<FrameworkElement> 
{ 
    public Key? ModifierKey { get; set; } = null; 
    public TransformMode TranformMode { get; set; } = TransformMode.Render; 

    private Transform _transform; 

    protected override void OnAttached() 
    { 
     if (TranformMode == TransformMode.Render) 
     { 
      _transform = AssociatedObject.RenderTransform = new MatrixTransform(); 
     } 
     else 
     { 
      _transform = AssociatedObject.LayoutTransform = new MatrixTransform(); 
     } 

     AssociatedObject.MouseWheel += AssociatedObject_MouseWheel; 
    } 

    protected override void OnDetaching() 
    { 
     AssociatedObject.MouseWheel -= AssociatedObject_MouseWheel; 
    } 

    private void AssociatedObject_MouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     if ((!ModifierKey.HasValue || !Keyboard.IsKeyDown(ModifierKey.Value)) && ModifierKey.HasValue) 
     { 
      return; 
     } 

     if (!(_transform is MatrixTransform transform)) 
     { 
      return; 
     } 

     var pos1 = e.GetPosition(AssociatedObject); 
     var scale = e.Delta > 0 ? 1.1 : 1/1.1; 
     var mat = transform.Matrix; 
     mat.ScaleAt(scale, scale, pos1.X, pos1.Y); 
     transform.Matrix = mat; 
     e.Handled = true; 
    } 
} 

public enum TransformMode 
{ 
    Layout, 
    Render, 
} 

Vous pouvez l'utiliser comme ceci:

<Grid> 
    <interactivity:Interaction.Behaviors> 
     <behaviors:ZoomOnMouseWheel /> 
    </interactivity:Interaction.Behaviors> 
    <!--Your grid content here--> 
</Grid> 

Ne pas oublier les xmlns:

xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity" 
+0

J'ai ajouté la possibilité de faire défiler seulement quand une touche de modification, comme 'LeftCtrl' est maintenue à travers la propriété 'ModifierKey', et la possibilité de contrôler si la transformation est effectuée en tant que RenderTranform ou LayoutTransform à travers la propriété TransformMode. Il est par défaut 'RenderTransform', mais si vous placez l'élément avec le' Behavior' dans un scrollviewer, et le définissez 'LayoutTransform', vous pouvez obtenir des barres de défilement lorsque vous zoomez. –