WPF 滚动视图器和平移

4
我有一个拥有ScrollViewerWindow,在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();
    }
}

将一个Canvas放入ScrollViewer中,并将Rectangle添加到Canvas中。然后通过设置其Canvas.Left和Canvas.Top属性来移动Rectangle。通过设置其Width和Height来缩放它。 - Clemens
@Clemens:我已经更新了我的代码,但仍然看不到滚动条。 - Franz Gsell
您可能还想设置画布的宽度和高度。 - Clemens
1个回答

2
如果您想让变换影响布局,您必须使用 LayoutTransform。而 RenderTransform 只会改变外观。
引用块中提到: 与元素的 LayoutTransform 属性相关联的任何转换都将影响后续的测量和排列步骤。而 RenderTransform 不会对布局过程产生任何影响,只会影响呈现。
如果您需要了解更多信息,请单击 此处
然而,LayoutTransform 忽略了 TranslateTransform
引用块中提到: LayoutTransform 忽略 TranslateTransform 操作。这是因为 FrameworkElement 的子元素的布局系统行为会自动更正缩放或旋转元素的位置偏移,以使其符合父元素的布局和坐标系统。
如果您需要了解更多信息,请单击 此处
所有这些意味着,要实现移动元素,您不能使用 Transforms。您可以尝试手动更改元素的位置(例如使用 Margin, Canvas.Left/Right 或其他想法)。

首先感谢您的回答。您能否举个例子,说明一下“手动更改元素位置”的意思? - Franz Gsell
你可以像这样使用画布:https://dev59.com/x3NA5IYBdhLWcg3wBo9m在这种情况下,当矩形即将移出其边界时,您还需要记住更改画布大小。 - Jonatan Dragon
有两个问题需要处理。1. 第一件事是移动您的对象 - 我们成功了。2. 第二个问题是您的画布大小。即使您移动矩形,画布大小仍然相同。滚动条的外观取决于画布大小(在这种情况下)。您可以通过编程方式更改它,或者查看此带有网格解决方案的解决方案:https://dev59.com/znRA5IYBdhLWcg3wtwSe - Jonatan Dragon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接