WPF鼠标拖拽的最佳实现

WPF鼠标拖拽的最佳实现

在很多项目中都会遇到鼠标拖拽控件移动的需求,常见的有从在列表中拖拽列表项移动,拖拽控件移动等。

本文将介绍2种拖拽的简单的实现

列表项的拖拽

本文将使用 gong-wpf-dragdrop 这个github上的库来实现列表的拖拽的效果,项目地址

优点非常简单,几行代码就可以实现效果了。

1.先看最终效果

2.实现过程

  1. 在Neget中搜索并安装gong-wpf-dragdrop库

  2. 在需要拖拽的列表控件上添加代码

            <ListBox
                x:Name="MyListBox"
                dd:DragDrop.DropHandler="{Binding}"
                dd:DragDrop.DropTargetAdornerBrush="{DynamicResource PrimaryThemeColor}"
                dd:DragDrop.IsDragSource="True"
                dd:DragDrop.IsDropTarget="True"
                dd:DragDrop.UseDefaultDragAdorner="True"
                ItemsSource="{Binding PipeList}"
                SelectionChanged="ListBox_SelectionChanged">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <Border Height="40">
                            <Grid Background="Transparent">
                                <TextBlock VerticalAlignment="Center" Text="{Binding}" />
                            </Grid>
                        </Border>
                    </DataTemplate>
                </ListBox.ItemTemplate>
        </ListBox>
    

    并且引入命名空间

    xmlns:dd="urn:gong-wpf-dragdrop"
    

    此时就能看到列表已经可以被拖拽排序了

    此时会有一点小瑕疵,那就是预览项并不会出现在鼠标点下的位置,而是在光标的上边,这时需要通过 DragAdornerTranslation 属性来控制偏移,实现一个更好的拾起效果,在列表中添加事件SelectionChanged 代码如下:

            private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
    
                // 获取当前选中项的ListBoxItem
                ListBoxItem selectedItem = (ListBoxItem)MyListBox.ItemContainerGenerator.ContainerFromItem(MyListBox.SelectedItem);
    
                if (selectedItem != null)
                {
                    // 获取鼠标相对于当前选中项的位置
                    Point position = Mouse.GetPosition(selectedItem);
    
                    // 偏移鼠标相对于当前选中项的位置
                    GongSolutions.Wpf.DragDrop.DragDrop.SetDragAdornerTranslation(MyListBox, new Point(-position.X, position.Y));//= "10,10"
    
                }
        	}
    

    最终就实现了我们需要的效果

控件的拖拽

控件的拖拽移动比较简单,就是直接使用代码实现了,主要会用到鼠标的三个事件

  • PreviewMouseDown 鼠标按下
  • PreviewMouseMove 鼠标移动
  • PreviewMouseUp 鼠标抬起

先看效果

实现过程

通过TranslateTransform来实现更改控件的位置,通过鼠标按下事件中,记录的按下时的鼠标坐标,和控件当前坐标,通过鼠标 移动事件中,鼠标位置偏移量,还原到控件上,就实现了这个效果,代码如下

xaml文件代码:

          <Button
              Width="120"
              Height="40"
              Content="Test"
              PreviewMouseDown="Button_PreviewMouseDown"
              PreviewMouseMove="Button_PreviewMouseMove"
              PreviewMouseUp="Button_PreviewMouseUp" />

cs代码:

public bool isMouseDown = false;
public Point mouseDownPosition;
public Point mouseDownControlPosition;
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    isMouseDown = true;

    var ctl = sender as UIElement;
    mouseDownPosition = e.GetPosition(null);

    var transform = ctl.RenderTransform as TranslateTransform;
    if (transform == null)
    {
        transform = new TranslateTransform();
        ctl.RenderTransform = transform;
    }
    mouseDownControlPosition = new Point(transform.X, transform.Y);
    ctl.CaptureMouse();
}

private void Button_PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (isMouseDown)
    {
        var button = (UIElement)sender;
        TranslateTransform transform = button.RenderTransform as TranslateTransform;
        Point currentPoint = e.GetPosition(null);
        double offsetX = currentPoint.X - mouseDownPosition.X;
        double offsetY = currentPoint.Y - mouseDownPosition.Y;

        double newX = mouseDownControlPosition.X + offsetX;
        double newY = mouseDownControlPosition.Y + offsetY;

        transform.X = newX;
        transform.Y = newY;
    }
}

private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    var ctl = sender as UIElement;
    isMouseDown = false;
    ctl.ReleaseMouseCapture();
}

这样就实现了控件移动的效果

相关推荐
晚安苏州1 小时前
WPF DataTemplate 数据模板
wpf
甜甜不吃芥末1 天前
WPF依赖属性详解
wpf
Hat_man_1 天前
WPF制作图片闪烁的自定义控件
wpf
晚安苏州2 天前
WPF Binding 绑定
wpf·wpf binding·wpf 绑定
wangnaisheng2 天前
【WPF】RenderTargetBitmap的使用
wpf
dotent·3 天前
WPF 完美解决改变指示灯的颜色
wpf
orangapple4 天前
WPF 用Vlc.DotNet.Wpf实现视频播放、停止、暂停功能
wpf·音视频
ysdysyn4 天前
wpf mvvm 数据绑定数据(按钮文字表头都可以),根据长度进行换行,并把换行的文字居中
c#·wpf·mvvm
orangapple4 天前
WPF 使用LibVLCSharp.WPF实现视频播放、停止、暂停功能
wpf
晚安苏州4 天前
WPF ControlTemplate 控件模板
wpf