如何在鼠标位置放大或缩小时正确同步 WPF Scrollviewer 和 Canvas

问题描述

我在 WPF (XAML) 代码中使用以下控件来创建画布:

<ScrollViewer x:Name="CanvasScrollViewer"  HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Background="Beige"  >
<Canvas x:Name="canvas"  Height="10000" Width="10000"   MouseWheel="CanvasMouseWheel" >
    <Canvas.RenderTransform>
        <MatrixTransform/>
    </Canvas.RenderTransform>
</Canvas>

本质上,这包括一个画布(比我的屏幕分辨率大)和一个滚动查看器,以确保我可以在整个画布上导航。

现在,如果我按住 CTRL 并使用鼠标滚轮,我想放大/缩小 在画布的当前鼠标光标位置。使用类似于列出的 here方法,它工作得很好。

我的 C# 代码如下所示:

private void CanvasMouseWheel(object sender,MouseWheelEventArgs e)
{
    if (Keyboard.Modifiers != ModifierKeys.Control)
        return;

    var sentCanvas = sender as UIElement;
    var position = e.GetPosition(sentCanvas);

    var transform = canvas.RenderTransform as MatrixTransform;
    var matrix = transform.Matrix;
    var scale = e.Delta >= 0 ? 1.2 : (1.0 / 1.2); 

    matrix.ScaleAtPrepend(scale,scale,position.X,position.Y);
    transform.Matrix = matrix;
    e.handled = true;
}

这很有效,但有一个例外:如果我向内/向外滚动,滚动查看器的滚动条位置和画布的实际位置不再同步。含义:画布放大或缩小,但滚动查看器不会调整其滚动条位置,这最终意味着您无法再正确滚动画布。 自然地(因为我使用画布来绘制需要大量导航的大型图表),我希望能够不时缩小很多,以便整个画布只填充滚动的一部分视野观众。附加的屏幕截图显示了我放大了很多的情况。

enter image description here

我尝试了其他几种方法,例如首先将滚动查看器移动到鼠标位置,然后应用“scale(...)”操作(没有“AtPrepend”),但无济于事。直接在滚动查看器上执行缩放操作显然也不起作用。或许,解决办法很简单,但见树不见林...

任何帮助将不胜感激!

解决方法

感谢 BionicCode 的提示。以下条目回答了我的问题并且非常有效:

WPF Canvas zoom and children position