WPF ScrollViewer 和平移

WPF ScrollViewer and Panning

我有一个 Window 和一个 ScrollViewer,在 ScrollViewer 里面有一个 Rectangle。现在我添加了代码来拖动 Rectangle ,效果很好。但是当 Rectangle 移出视图时,我不知道如何显示 Scrollbars。我以为这会自动发生,但事实并非如此?

这是我的 XAML:

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <ScrollViewer Name="_scrollViewer" CanContentScroll="True" 
                  HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue"/>
    </ScrollViewer>
</Window>

后面的代码:

public partial class MainWindow : Window
{
    private Point _origin;
    private Point _start;
    private ScaleTransform _scaleTransform = new ScaleTransform();
    private TranslateTransform _translateTransform = new TranslateTransform();

    public MainWindow()
    {
        InitializeComponent();

        var group = new TransformGroup();
        group.Children.Add(_scaleTransform);
        group.Children.Add(_translateTransform);  
        _myRect.RenderTransform = group;

        // Hook up events
        _myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
        _myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
        _myRect.MouseMove += _myRect_MouseMove;
    }

    private void _myRect_MouseMove(object sender, MouseEventArgs e)
    {
        if (_myRect.IsMouseCaptured)
        {
            Vector v = _start - e.GetPosition(this);
            _translateTransform.X = _origin.X - v.X;
            _translateTransform.Y = _origin.Y - v.Y;
        }
    }

    private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _myRect.ReleaseMouseCapture();
        this.Cursor = Cursors.Arrow;
    }

    private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _start = e.GetPosition(this);
        _origin = new Point(_translateTransform.X, _translateTransform.Y);
        Cursor = Cursors.Hand;
        _myRect.CaptureMouse();
    }
}

[更新]: 因此,根据我得到的输入,我将 XAML 和后面的代码更改为以下内容 - 但仍然没有滚动条?

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <ScrollViewer Name="_scrollViewer" CanContentScroll="True" 
                  HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
        <Canvas Name="_myCanvas">
            <Rectangle Name="_myRect" Width="100" Height="100" Fill="Blue" Canvas.Left="305" Canvas.Top="129"/>
        </Canvas>
    </ScrollViewer>
</Window>

隐藏代码:

public partial class MainWindow : Window
{
    private Point _start;

    public MainWindow()
    {
        InitializeComponent();
        // Hook up events
        _myRect.MouseLeftButtonDown += _myRect_MouseLeftButtonDown;
        _myRect.MouseLeftButtonUp += _myRect_MouseLeftButtonUp;
        _myRect.MouseMove += _myRect_MouseMove;
    }

    private void _myRect_MouseMove(object sender, MouseEventArgs e)
    {
        if (_myRect.IsMouseCaptured)
        {
            var canvasRelativePosition = e.GetPosition(_myCanvas);
            Debug.WriteLine($"New Position: {canvasRelativePosition}");
            Canvas.SetTop(_myRect, canvasRelativePosition.Y - _start.Y);
            Canvas.SetLeft(_myRect, canvasRelativePosition.X - _start.X);
        }
    }

    private void _myRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _myRect.ReleaseMouseCapture();
        this.Cursor = Cursors.Arrow;
    }

    private void _myRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _start = e.GetPosition(_myRect);
        Debug.WriteLine($"Start Position: {_start}");
        Cursor = Cursors.Hand;
        _myRect.CaptureMouse();
    }
}

如果您希望变换影响布局,则必须使用 LayoutTransofrmRenderTransform 只改变外观。

Any transformations associated with an elements LayoutTransform property will have an impact on the subsequent Measure and Arrange steps. Whereas a RenderTransform will not have any impact on the layout process and will only effect rendering.

阅读更多here

但是,LayoutTransform 忽略了 TranslateTransform

LayoutTransform ignores TranslateTransform operations. This is because the layout system behavior for child elements of a FrameworkElement auto-corrects any offsets to the position of a scaled or rotated element into the layout and coordinate system of the parent element.

阅读更多here

也就是说,要实现元素的移动,不能使用Transforms。您可以尝试手动更改元素的位置(MarginCanvas.Left/Right 或其他想法)。