问题
<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>
The reference point is fixed with Left and Top points to zoom the Canvas. I'd like to zoom in and zoom out on the mouse pointer. How do I make it into the MVVM Pattern? (Not Behind code). Using mouse wheel, I can zoom in canvas. I already use RenderTransformOrigin, CenterX, CenterY but it is not worked. I think I made a wrong approach. Please help me..
回答1:
Since you didn't provide your current zooming code, here is a generic example of zooming on the mouse position:
<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>
With code that updates the transformation matrix:
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;
}
回答2:
I took @Grek40's code and converted it in to a Behavior for anyone trying to stick with the MVVM pattern. If you up-vote this, please remember to also up-vote his answer too, as mine is based on his work. It requires the System.Windows.Interactivity.WPF nuget package
(or some other framework) for the Behavior base-class. You can apply this to any UIElement. It will automatically add the MatrixTransform for you, so you don't have to do that in XAML (it will overwrite any existing transform).
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,
}
You can use it like this:
<Grid>
<interactivity:Interaction.Behaviors>
<behaviors:ZoomOnMouseWheel />
</interactivity:Interaction.Behaviors>
<!--Your grid content here-->
</Grid>
Don't forget the xmlns:
xmlns:interactivity="http://schemas.microsoft.com/expression/2010/interactivity"
来源:https://stackoverflow.com/questions/46424149/wpf-zoom-canvas-center-on-mouse-position