user1202434
user1202434

Reputation: 2273

Make a StackPanel and its contents "draggable" in wpf?

I have a UserControl in the form of:

<UserControl>   
    <Grid>         
          <!-- Content Here-->    
      <StackPanel>   <!-- I want this element to be draggable within the usercontrol. -->    
         <Label Name = "Header" />  
         <Button />
         <Button />
         <Button />             
         </StackPanel>    
   <Grid>             
</UserControl>

My end result is to have a control with buttons (part of the usercontrol) that can be dragged around..? That is, moveable ... within the UserControl

Ive read about Thumb but I am not sure how to use it...Any ideas or examples would be great.Thanks!

Upvotes: 4

Views: 14870

Answers (6)

user15719632
user15719632

Reputation:

Here is an actual working example of a Draggable Rectangle in WPF, This is exactly what Rachel is talking about above.

You can put any UserControl/StackPanel/Grid etc inside the Canvas tag.

I made this because I was having an issue dragging a StackPanel, the problem was actually that I had set a Margin on the panel so it was being offset.

This won't skip around when you drag it.

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Canvas x:Name="canvas" Background="Transparent" PreviewMouseLeftButtonDown="PreviewDown" PreviewMouseLeftButtonUp="PreviewUp" MouseMove="MoveMouse">
            <Rectangle x:Name="Rectangle" HorizontalAlignment="Left" Fill="Black" Height="85" Margin="0" Stroke="Black" VerticalAlignment="Top" Width="82" />
        </Canvas>
    </Grid>
</Window>

XAML

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private object movingObject;
        private double firstXPos, firstYPos;

        private void PreviewDown(object sender, MouseButtonEventArgs e)
        {
            firstXPos = e.GetPosition(Rectangle).X;
            firstYPos = e.GetPosition(Rectangle).Y;

            movingObject = sender;
        }

        private void PreviewUp(object sender, MouseButtonEventArgs e)
        {
            movingObject = null;
        }

        private void MoveMouse(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && sender == movingObject)
            {
                double newLeft = e.GetPosition(canvas).X - firstXPos - canvas.Margin.Left;

                Rectangle.SetValue(Canvas.LeftProperty, newLeft);

                double newTop = e.GetPosition(canvas).Y - firstYPos - canvas.Margin.Top;

                Rectangle.SetValue(Canvas.TopProperty, newTop);
            }
        }
    }
}

MainWindow.cs

Upvotes: 2

Rachel
Rachel

Reputation: 132618

A very simple way to do it would be to use mouse events

First off, wrap your StackPanel in a Canvas so it can be easily positioned according to where the user drags it

Next, add MouseDown and MouseUp events to the StackPanel. You may need to give your StackPanel a background color for it to receive mouse events.

In the MouseDown event, attach a MouseMove event handler to the StackPanel and have the panel capture the mouse so all mouse events will get handled by the StackPanel.

In the MouseUp event, detach the MouseMove event and release your mouse capture.

In the MouseMove event, change the Canvas.Top and Canvas.Left properties of the panel based on the current Mouse position. You will need a check here to determine if the mouse is outside of the UserControl too so the StackPanel can't be dragged off screen.

And that's it, very basic drag drop :)

Upvotes: 12

Steve B
Steve B

Reputation: 37710

You should give a chance to the avalondock project.

This allows you to create rich layout features, like Visual Studio does (floating, docking, etc.).

I'm confident this would help you.

Upvotes: 0

Hasan Zubairi
Hasan Zubairi

Reputation: 1183

There are some tutorials available for this on MSDN and other places. Try the following link for WPF drag and drop.

WPF Drag and Drop

Upvotes: 0

Can Poyrazoğlu
Can Poyrazoğlu

Reputation: 34810

I don't know of any specific method but intuitively, you may add an event handler to drag method of the control you want to move, and in that method, you may render the control to a bitmap, make that bitmap follow your mouse pointer, and hide the original control. When dropped (mouse released), it should simply set the original control's coordinates to mouse coordinates, dispose of the bitmap, and re-enable the visibility of the control.

Upvotes: 0

Ignacio Soler Garcia
Ignacio Soler Garcia

Reputation: 21855

One way would be to handle the mouseclick on the button and change its position while moving the mouse.

So the steps will be:

  1. Add a handler to the button. Mouseclick for example (or mousedown)
  2. When you receive a mouseclick add a handler to mousemove.
  3. Check the movement of the mouse and change the position of the button
  4. Remove the handler after releasing the mouse button.

Upvotes: 0

Related Questions