WPF ScrollViewer и панорамирование - PullRequest
3 голосов
/ 04 июня 2019

У меня есть Window с ScrollViewer, а внутри ScrollViewer есть Rectangle. Теперь я добавил код для перетаскивания Rectangle, который отлично работает. Но я понятия не имею, как показать Scrollbars, когда Rectangle перемещен за пределы вида. Я думал, что это произойдет автоматически, что не так?

Вот мой 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();
    }
}

1 Ответ

1 голос
/ 04 июня 2019

Если вы хотите, чтобы ваше преобразование влияло на макет, вы должны использовать LayoutTransofrm.RenderTransform только изменяет внешний вид.

Любые преобразования, связанные со свойством LayoutTransform элементов, будут влиять на последующие этапы Measure и Arrange.Принимая во внимание, что RenderTransform не будет иметь никакого влияния на процесс макета и будет влиять только на рендеринг.

Подробнее здесь .

Однако LayoutTransform игнорирует TranslateTransform

LayoutTransform игнорирует операции TranslateTransform.Это связано с тем, что поведение системы компоновки для дочерних элементов FrameworkElement автоматически корректирует любые смещения для положения масштабированного или повернутого элемента в компоновке и системе координат родительского элемента.

Подробнее здесь

Все это означает, что для достижения перемещения вашего элемента вы не можете использовать Transforms.Вы можете попытаться изменить положение вашего элемента вручную (Margin, Canvas.Left/Right или другие идеи).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...