Применение TranslateTranform к моему холсту очень нервный WPF - PullRequest
1 голос
/ 14 мая 2019

Я пытаюсь применить преобразование Translate к своему холсту, используя прикрепленные свойства - холст перемещается, когда я его перетаскиваю, но он очень нервный и постоянно пытается вернуться к исходному положению.Когда я прокручиваю свой холст, он также полностью портится и перетаскивает холст за пределы экрана.

Мои методы класса прикрепленных свойств:


private Point _originalMouseDownPoint;


 private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs) {
            var pos = mouseEventArgs.GetPosition(AssociatedObject);
            MouseX = pos.X;
            MouseY = pos.Y;
            var canvas = sender as Canvas;
            if (BaseViewModel.Mode != MouseHandlingModeEnum.Panning) return;
            var translateTransform = new
                TranslateTransform(pos.X - _originalMouseDownPoint.X, pos.Y - _originalMouseDownPoint.Y);

            canvas.RenderTransform = translateTransform;
        }

        private void AssociatedObjectOnMouseDown(object sender, MouseButtonEventArgs e) {
            var canvas = sender as Canvas;
            canvas.CaptureMouse();
            canvas.Focus();
            _originalMouseDownPoint = e.GetPosition(canvas);
            BaseViewModel.Mode = MouseHandlingModeEnum.Panning;
        }

private void AssociatedObjectOnMouseUp(object sender, MouseButtonEventArgs e) {
            var canvas = sender as Canvas;
            canvas.ReleaseMouseCapture();
            BaseViewModel.Mode = MouseHandlingModeEnum.None;
        }

И тогда мой XAML просто устанавливает это с помощью поведения canvas.

<i:Interaction.Behaviors>
                    <attachedProperties:MouseBehaviour  MouseX="{Binding PanelX , Mode=OneWayToSource}"
                                           MouseY="{Binding PanelY, Mode=OneWayToSource}" />

                    </i:Interaction.Behaviors>

(Игнорируйте привязки, они для отдельной функциональности.

Программа должна плавно перемещаться по холсту. Я видел, как некоторые люди используют матричное преобразование, если я попробуюи реализовать это каким-то образом?

Ответы [ 2 ]

0 голосов
/ 16 мая 2019
public class MouseBehaviour : Behavior<Panel> {
    public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
        "MouseY", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

    public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
        "MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));

    private Point _originalMouseDownPoint;
    private double _hOff = 1;
    private double _vOff = 1;


    public double MouseY {
        get => (double)GetValue(MouseYProperty);
        set => SetValue(MouseYProperty, value);
    }

    public double MouseX {
        get => (double)GetValue(MouseXProperty);
        set => SetValue(MouseXProperty, value);

    }

    protected override void OnAttached() {
        AssociatedObject.MouseUp += AssociatedObjectOnMouseUp;
        AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
        AssociatedObject.MouseDown += AssociatedObjectOnMouseDown;
    }
    protected override void OnDetaching()
    {
        AssociatedObject.MouseUp -= AssociatedObjectOnMouseUp;
        AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
        AssociatedObject.MouseDown -= AssociatedObjectOnMouseDown;

    }
    /// <summary>
    /// Deals with mouse movement event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="mouseEventArgs"></param>oop
    private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs) {
        //Keep track of position of mouse on the canvas
        var canvasPosition = mouseEventArgs.GetPosition(AssociatedObject);

        MouseX = canvasPosition.X;
        MouseY = canvasPosition.Y;

        //If we're currently panning
        var canvas = sender as Canvas;
        var scrollViewer = canvas.Parent as ScrollViewer;

        //Position of the scroll viewer
        var scrollPosition = mouseEventArgs.GetPosition(scrollViewer);

        if (BaseViewModel.Mode != MouseHandlingModeEnum.Panning) return;

        //Then update the scroll viewer based on our mouse movement
        scrollViewer.ScrollToHorizontalOffset(
            _hOff + (_originalMouseDownPoint.X - scrollPosition.X));
        scrollViewer.ScrollToVerticalOffset(_vOff + (_originalMouseDownPoint.Y - scrollPosition.Y));




    }
    /// <summary>
    /// Deals with the mouse down event on the canvas
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void AssociatedObjectOnMouseDown(object sender, MouseButtonEventArgs e)
    {
        var canvas = sender as Canvas;
        var scrollViewer = canvas.Parent as ScrollViewer;

        //Gives the current offset of the scroll viewer
        _hOff = scrollViewer.HorizontalOffset;
        _vOff = scrollViewer.VerticalOffset;
        _originalMouseDownPoint = e.GetPosition(scrollViewer);

        BaseViewModel.Mode = MouseHandlingModeEnum.Panning;
        canvas.CaptureMouse();
        canvas.Focus();

    }




    /// <summary>
    /// Deals with mouse up event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void AssociatedObjectOnMouseUp(object sender, MouseButtonEventArgs e)
    {
        var canvas = sender as Canvas;
        canvas.ReleaseMouseCapture();

        BaseViewModel.Mode = MouseHandlingModeEnum.None;
    }
}

Для будущих читателей я в конечном итоге использовал свой ScrollViewer, который вместо этого обернул мой Canvas в панорамирование по холсту, и теперь, похоже, он работает довольно хорошо.

0 голосов
/ 15 мая 2019

По своему опыту я обнаружил, что мне нравится работать с Canvas.Left / Top, когда мне нужно просто перетаскивать или перемещать объекты простым способом.Я использую преобразования, когда я делаю что-то более сложное (что редко).Обычно это проще для отладки и более упорядоченным.Вы можете сделать что-то вроде этого:

private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs) {
        var pos = mouseEventArgs.GetPosition(AssociatedObject);
        MouseX = pos.X;
        MouseY = pos.Y;
        var canvas = sender as Canvas;
        if (BaseViewModel.Mode != MouseHandlingModeEnum.Panning) return;

           Canvas.SetLeft(AssociatedObject, MouseX - _originalMouseDownPoint.X);
           Canvas.SetTop(AssociatedObject, MouseY - _originalMouseDownPoint.Y);
    }

    private void AssociatedObjectOnMouseDown(object sender, MouseButtonEventArgs e) {
        var canvas = sender as Canvas;
        canvas.CaptureMouse();
        canvas.Focus();
        _originalMouseDownPoint = e.GetPosition((UIElement)sender);
        BaseViewModel.Mode = MouseHandlingModeEnum.Panning;
    }

private void AssociatedObjectOnMouseUp(object sender, MouseButtonEventArgs e) {
        var canvas = sender as Canvas;
        canvas.ReleaseMouseCapture();
        _originalMouseDownPoint = null;
        BaseViewModel.Mode = MouseHandlingModeEnum.None;
    }

Я предполагаю, что ваш BaseViewModel.Mode является флагом для указания условия перетаскивания.

Если вы хотите привязать виртуальную машину к перетаскиванию, вы можете добавить Свойства для Позиции и получить доступ к DataContext напрямую (var vm = DataContext as AssociatedObjectViewModel) и установить новые позиции.Затем в XAML вы можете связать Canvas.Left и Canvas.Top с этими свойствами.Однако это не всегда возможно в зависимости от того, как вы все настроили, и иногда это проще / чище позаботиться об этом в Code Behind.

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