简体   繁体   English

在 wpf 中使 StackPanel 及其内容“可拖动”?

[英]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也就是说,在 UserControl 中可移动...

Ive read about Thumb but I am not sure how to use it...Any ideas or examples would be great.Thanks!我读过关于 Thumb 的内容,但我不知道如何使用它......任何想法或例子都会很棒。谢谢!

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首先,将StackPanel包裹在Canvas以便根据用户拖动它的位置轻松定位

Next, add MouseDown and MouseUp events to the StackPanel .接下来,将MouseDownMouseUp事件添加到StackPanel You may need to give your StackPanel a background color for it to receive mouse events.您可能需要为StackPanel提供背景颜色以接收鼠标事件。

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 .MouseDown事件中,将MouseMove事件处理程序附加到StackPanel并让面板捕获鼠标,以便StackPanel处理所有鼠标事件。

In the MouseUp event, detach the MouseMove event and release your mouse capture.MouseUp事件中,分离MouseMove事件并释放鼠标捕获。

In the MouseMove event, change the Canvas.Top and Canvas.Left properties of the panel based on the current Mouse position.MouseMove事件中,根据当前鼠标位置更改面板的Canvas.TopCanvas.Left属性。 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.您需要在此处进行检查以确定鼠标是否也在UserControl之外,因此无法将StackPanel拖出屏幕。

And that's it, very basic drag drop :)就是这样,非常基本的拖放:)

Here is an actual working example of a Draggable Rectangle in WPF, This is exactly what Rachel is talking about above.这是 WPF 中可拖动矩形的实际工作示例,这正是 Rachel 上面所说的。

You can put any UserControl / StackPanel / Grid etc inside the Canvas tag.您可以将任何UserControl / StackPanel / Grid等放在Canvas标签内。

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.我这样做是因为我在拖动StackPanel时遇到了问题,问题实际上是我在面板上设置了一个 Margin 所以它被抵消了。

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

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.当您收到 mouseclick 时,将处理程序添加到 mousemove。
  3. Check the movement of the mouse and change the position of the button检查鼠标的移动并改变按钮的位置
  4. Remove the handler after releasing the mouse button.释放鼠标按钮后删除处理程序。

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.当放下(鼠标释放)时,它应该简单地将原始控件的坐标设置为鼠标坐标,处理位图,并重新启用控件的可见性。

There are some tutorials available for this on MSDN and other places.在 MSDN 和其他地方有一些可用的教程。 Try the following link for WPF drag and drop.尝试使用以下链接进行 WPF 拖放。

WPF Drag and Drop WPF 拖放

You should give a chance to the avalondock project .你应该给avalondock 项目一个机会。

This allows you to create rich layout features, like Visual Studio does (floating, docking, etc.).这允许您创建丰富的布局功能,就像 Visual Studio 所做的一样(浮动、停靠等)。

I'm confident this would help you.我相信这会对你有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM