.net 在WPF中拖动图像

.net 在WPF中拖动图像,.net,wpf,user-interface,.net,Wpf,User Interface,我正在尝试创建一个WPF应用程序,可以在其中拖动图像 目前,我在窗口的中心放置了一个图像,我正在考虑使用三个mouseevents MouseDown、MouseMove和MouseUp来计算拖动图像时的新位置 关于如何做到这一点,还有其他好主意吗?我对WPF完全陌生,所以我的思维方式仍然是在Windows窗体世界 据我所知,我需要使用 为了使绝对定位可用。好的,这里有一个附加属性“行为”,您可以使用它使任何元素都可以拖动,只要它位于画布上: public class DraggableExte

我正在尝试创建一个WPF应用程序,可以在其中拖动图像

目前,我在窗口的中心放置了一个图像,我正在考虑使用三个mouseevents MouseDown、MouseMove和MouseUp来计算拖动图像时的新位置

关于如何做到这一点,还有其他好主意吗?我对WPF完全陌生,所以我的思维方式仍然是在Windows窗体世界

据我所知,我需要使用
为了使绝对定位可用。

好的,这里有一个附加属性“行为”,您可以使用它使任何元素都可以拖动,只要它位于画布上:

public class DraggableExtender : DependencyObject
{
    // This is the dependency property we're exposing - we'll 
    // access this as DraggableExtender.CanDrag="true"/"false"
    public static readonly DependencyProperty CanDragProperty =
        DependencyProperty.RegisterAttached("CanDrag",
        typeof(bool),
        typeof(DraggableExtender),
        new UIPropertyMetadata(false, OnChangeCanDragProperty));

    // The expected static setter
    public static void SetCanDrag(UIElement element, bool o)
    {
        element.SetValue(CanDragProperty, o);
    }

    // the expected static getter
    public static bool GetCanDrag(UIElement element)
    {
        return (bool) element.GetValue(CanDragProperty);
    }

    // This is triggered when the CanDrag property is set. We'll
    // simply check the element is a UI element and that it is
    // within a canvas. If it is, we'll hook into the mouse events
    private static void OnChangeCanDragProperty(DependencyObject d, 
              DependencyPropertyChangedEventArgs e)
    {
        UIElement element = d as UIElement;
        if (element == null) return;

        if (e.NewValue != e.OldValue)
        {
            if ((bool)e.NewValue)
            {
                element.PreviewMouseDown += element_PreviewMouseDown;
                element.PreviewMouseUp += element_PreviewMouseUp;
                element.PreviewMouseMove += element_PreviewMouseMove;
            }
            else
            {
                element.PreviewMouseDown -= element_PreviewMouseDown;
                element.PreviewMouseUp -= element_PreviewMouseUp;
                element.PreviewMouseMove -= element_PreviewMouseMove;
            }
        }
    }

    // Determine if we're presently dragging
    private static bool _isDragging = false;
    // The offset from the top, left of the item being dragged 
    // and the original mouse down
    private static Point _offset;

    // This is triggered when the mouse button is pressed 
    // on the element being hooked
    static void element_PreviewMouseDown(object sender,
            System.Windows.Input.MouseButtonEventArgs e)
    {
        // Ensure it's a framework element as we'll need to 
        // get access to the visual tree
        FrameworkElement element = sender as FrameworkElement;
        if (element == null) return;

        // start dragging and get the offset of the mouse 
        // relative to the element
        _isDragging = true;
        _offset = e.GetPosition(element);
    }

    // This is triggered when the mouse is moved over the element
    private static void element_PreviewMouseMove(object sender, 
              MouseEventArgs e)
    {
        // If we're not dragging, don't bother - also validate the element
        if (!_isDragging) return;

        FrameworkElement element = sender as FrameworkElement;
        if (element == null) return;

        Canvas canvas = element.Parent as Canvas;
        if( canvas == null ) return;

        // Get the position of the mouse relative to the canvas
        Point mousePoint = e.GetPosition(canvas);

        // Offset the mouse position by the original offset position
        mousePoint.Offset(-_offset.X, -_offset.Y);

        // Move the element on the canvas
        element.SetValue(Canvas.LeftProperty, mousePoint.X);
        element.SetValue(Canvas.TopProperty, mousePoint.Y);
    }

    // this is triggered when the mouse is released
    private static void element_PreviewMouseUp(object sender, 
            MouseButtonEventArgs e)
    {
        _isDragging = false;
    }

}
然后,您可以通过导入类所包含的名称空间在XAML中使用它(如下所示:)


然后,您可以在元素上设置DraggableExtender.CanDrag=“true”以进行拖动:

<Canvas>
    <Image Source="Garden.jpg" 
           Width="50" 
           Canvas.Left="10" Canvas.Top="10" 
           local:DraggableExtender.CanDrag="true"/>
</Canvas>


希望这有点用处:)

deepcode.co.uk提供的解决方案还可以;然而,在实现它时,我遗漏了一些功能,因此我正在扩展他的解决方案

当画布中有2个或更多元素时,还需要设置:

    private void Element_PreviewMouseDown(object sender, MouseEventArgs e)
    {
        element.CaptureMouse();
    }

    private void Element_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        element.ReleaseMouseCapture();
    }
这样,拖动操作将仅影响当前活动的图元

拖动时,也可能不希望元素超出画布的边界:

    if (mousePoint.X > 0 && mousePoint.X + element.ActualWidth <= canvas.ActualWidth &&
        mousePoint.Y > 0 && mousePoint.Y + element.ActualHeight <= canvas.ActualHeight)
    {
        element.SetValue(Canvas.LeftProperty, mousePoint.X);
        element.SetValue(Canvas.TopProperty, mousePoint.Y);
    }

谢谢-非常有用的代码。我会稍微改进它,让元素在鼠标中捕获鼠标,然后在鼠标中释放鼠标捕获。否则,如果由于某种原因,鼠标落在被拖动项目的边界之外,则很容易错过鼠标移动。好的一点-我刚刚对无铬窗口做了类似的操作,将添加该建议;)有没有办法强制仅在画布限制内拖动图像?
    if (mousePoint.X > 0 && mousePoint.X + element.ActualWidth <= canvas.ActualWidth &&
        mousePoint.Y > 0 && mousePoint.Y + element.ActualHeight <= canvas.ActualHeight)
    {
        element.SetValue(Canvas.LeftProperty, mousePoint.X);
        element.SetValue(Canvas.TopProperty, mousePoint.Y);
    }
    private void Element_PreviewMouseDown(object sender, MouseEventArgs e)
    {
        Panel.SetZIndex(element, 1);
    }

    private void Element_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        Panel.SetZIndex(element, 0);
    }