【问题标题】:wpf translating point relative to the window results in a offset when moving the UIElement移动 UIElement 时,相对于窗口的 wpf 平移点会导致偏移
【发布时间】:2017-07-18 12:58:59
【问题描述】:

我目前正在研究一个用鼠标拖动 UIElements 的行为类。我以前做过这样的事情,但我试图让 UIElement 不依赖于具有某种类型的父对象(除了窗口)。

我遇到的问题是,当我尝试平移鼠标和 UIElement(AssociatedObject) 相对于窗口的坐标时,导致出现如下所示的偏移。

尝试添加偏移来“修复”当前偏移感觉就像是在作弊,这会使创建其余的运动行为变得更加复杂。

目前我正在使用一个内部包含多个元素的网格来测试 dragBehaviorComponentClass。 (我用 lightBlue 填充了网格作为指示器,虽然它被其他形状略微重叠)

我目前只尝试将 uiElement 的 0,0 位置附加到鼠标点,我还没有处理任何偏移以进一步改进拖动。

代码

public class MouseDragBehaviourComponent : Behavior<UIElement>
    {
        private TranslateTransform transform = new TranslateTransform();

        protected override void OnAttached()
        {
            AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
            AssociatedObject.PreviewMouseMove += AssociatedObject_PreviewMouseMove;
            AssociatedObject.MouseMove += AssociatedObject_MouseMove;
            AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
        }

        private void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            AssociatedObject.ReleaseMouseCapture();
        }
        private void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

        {
            Point currentPosition = AssociatedObject.TranslatePoint(new Point(0, 0), Window.GetWindow(AssociatedObject));
            AssociatedObject.RenderTransform = transform;
            AssociatedObject.CaptureMouse();
        }

        private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
        {
            if (AssociatedObject.IsMouseCaptured)
            {
                Point mousePosition = e.GetPosition(Window.GetWindow(AssociatedObject));
                transform.X = mousePosition.X;
                transform.Y = mousePosition.Y;
            }

        }

xaml

<Setter Property="Template">
            <Setter.Value>
                <ControlTemplate  TargetType="{x:Type local:UISet}">
                    <Border >
                        <e:Interaction.Behaviors>
                            <bt:MouseDragBehaviourComponent/>
                        </e:Interaction.Behaviors>
                        <Grid Background="LightBlue">
                            <StackPanel>
                                <Path MouseLeftButtonDown="geometry_MouseLeftButtonDown" Name="geometry" Fill="Blue">
                                <Path.Data>
                                    <CombinedGeometry GeometryCombineMode="Exclude">
                                        <CombinedGeometry.Geometry1>
                                    <RectangleGeometry RadiusX="2" RadiusY="2" Rect="-5,-50,100,50" />
                                        </CombinedGeometry.Geometry1>
                                        <CombinedGeometry.Geometry2>
                                            <RectangleGeometry RadiusX="2" RadiusY="2" Rect="5,-40,90,40" />
                                        </CombinedGeometry.Geometry2>
                                    </CombinedGeometry>
                                </Path.Data>
                            </Path>
                            <Path MouseLeftButtonDown="geometry_MouseLeftButtonDown" Fill="Red">
                                <Path.Data>
                                    <PathGeometry>
                                        <PathFigure StartPoint="0,0">
                                            <LineSegment Point="5,6"/>
                                            <LineSegment Point="10,0"/>
                                            <LineSegment Point="0,0"/>
                                        </PathFigure>
                                    </PathGeometry>
                                </Path.Data>
                            </Path>
                        </StackPanel>
                    </Grid>

【问题讨论】:

  • 为什么不直接使用 Blend SDK 中的 MouseDragElementBehavior 并省去麻烦?
  • 我实际上希望能够做的不仅仅是移动它们,从快速移动到正常移动到根据状态替换多个控件。虽然我不认为我必须包括这个,因为它不是问题的一部分

标签: c# wpf events blend


【解决方案1】:

您的代码设置方式:

transform.X = mousePosition.X;
transform.Y = mousePosition.Y;

在您移动的物体内获取鼠标位置。无论距离是多少,这都会导致变换远离鼠标。要解决这个问题,您需要获取您正在移动的东西的容器的鼠标位置,该容器将作为主要点,并且还需要在您正在移动的东西内获取光标的鼠标位置。这将作为偏移量。所以总而言之,代码看起来类似于:

Point mouseContainerLocation = Mouse.GetPosition(container);
Point mouseObjectLocation = Mouse.GetPosition(object);
transform.X = mouseContainerLocation.X - mouseObjectLocation.X;
transform.Y = mouseContainerLocation.Y - mouseObjectLocation.Y;

我在我制作的应用程序中做了类似的事情,这对我有用

【讨论】:

  • 您是否仍然可以使用窗口作为容器来使用它,否则您将不得不沿着可视化树查找兼容的父级。我试过了,控件会跳出屏幕。我使用 Window.getWindow(associatedObject) 作为获取 MainWindow 的容器。然后我使用了 associatedObject 作为“对象”。 uiElement 完全跳出屏幕。
  • 如果你使用Mouse.GetPosition(null),它将返回鼠标相对于窗口的位置
猜你喜欢
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 2018-04-28
  • 2013-09-04
  • 2015-06-18
  • 1970-01-01
相关资源
最近更新 更多