C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > WPF ListBox拖动子项

基于WPF实现ListBox拖动子项

作者:WPF开发者

这篇文章主要为大家详细介绍了如何基于WPF实现ListBox拖动子项效果,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考下

WPF 实现 ListBox 拖动子项

框架支持.NET4 至 .NET8

Visual Studio 2022;

图片

实现代码

XAML 部分

1)新增 MainWindow.xaml 代码如下:

<wd:Window
    x:Class="WPFListBoxItemDrag.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:local="clr-namespace:WPFListBoxItemDrag"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
    Title="WPF开发者 - ListBoxItemDrag"
    Width="800"
    Height="450"
    WindowStartupLocation="CenterScreen"
    mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListBox
            x:Name="ListBoxStart"
            AllowDrop="True"
            BorderThickness="1"
            ItemsSource="{Binding ItemsA}"
            PreviewMouseLeftButtonDown="ListBoxStart_PreviewMouseLeftButtonDown"
            PreviewMouseLeftButtonUp="ListBoxStart_PreviewMouseLeftButtonUp"
            PreviewMouseMove="ListBoxStart_PreviewMouseMove" />
        <Canvas
            x:Name="DragCanvas"
            Grid.ColumnSpan="2"
            Panel.ZIndex="1000" />
        <ListBox
            x:Name="ListBoxEnd"
            Grid.Column="1"
            AllowDrop="True"
            Drop="ListBoxEnd_Drop"
            ItemsSource="{Binding ItemsB}" />
    </Grid>
</wd:Window>

CSharp 部分

2)新增 MainWindow.xaml.cs 代码如下:

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WPFListBoxItemDrag
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow 
    {
        private bool isDragging;
        private ListBoxItem item;
        private ListBoxItem dragItem;
        private object data;
        public ObservableCollection<string> ItemsA { get; set; }
        public ObservableCollection<string> ItemsB { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            ItemsA = new() { "WPFDevelopersOrg", "WPFDevelopers", "WPF开发者", "ListBox", "ListBoxItem" };
            ItemsB = new ObservableCollection<string>();
        }

        private void ListBoxStart_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            data = GetListBoxItemData(ListBoxStart, e.GetPosition(ListBoxStart));
            item = FindVisualParent<ListBoxItem>((DependencyObject)e.OriginalSource);
            if (item != null)
                isDragging = true;
        }

        private T FindVisualParent<T>(DependencyObject obj) where T : DependencyObject
        {
            while (obj != null)
            {
                if (obj is T)
                    return (T)obj;
                obj = VisualTreeHelper.GetParent(obj);
            }
            return null;
        }

        private object GetListBoxItemData(ListBox source, Point point)
        {
            var element = source.InputHitTest(point) as UIElement;
            if (element != null)
            {
                var data = DependencyProperty.UnsetValue;
                while (data == DependencyProperty.UnsetValue)
                {
                    data = source.ItemContainerGenerator.ItemFromContainer(element);

                    if (data == DependencyProperty.UnsetValue)
                        element = VisualTreeHelper.GetParent(element) as UIElement;
                    if (element == source)
                        return null;
                }
                if (data != DependencyProperty.UnsetValue)
                    return data;
            }
            return null;
        }

        private void ListBoxStart_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (data != null)
                DragDrop.DoDragDrop(ListBoxStart, data, DragDropEffects.Move);
            isDragging = false;
            if (dragItem != null)
            {
                DragCanvas.Children.Remove(dragItem);
                dragItem = null;
            }
        }

        private void ListBoxStart_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                if (dragItem == null)
                {
                    dragItem = new ListBoxItem
                    {
                        Content = item.Content,
                        Width = item.ActualWidth,
                        Height = item.ActualHeight,
                        Background = Brushes.Gray,
                        ContentTemplate = item.ContentTemplate,
                        ContentTemplateSelector = item.ContentTemplateSelector,
                        Style = item.Style,
                        Padding = item.Padding,
                        Opacity = .5,
                        IsHitTestVisible = false,
                    };
                    DragCanvas.Children.Add(dragItem);
                }
                var mousePos = e.GetPosition(DragCanvas);
                Canvas.SetLeft(dragItem, mousePos.X - dragItem.ActualWidth / 2);
                Canvas.SetTop(dragItem, mousePos.Y - dragItem.ActualHeight / 2);
            }
        }

        private void ListBoxEnd_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(string)))
            {
                var data = e.Data.GetData(typeof(string)).ToString();
                ItemsB.Add(data);
                ItemsA.Remove(data.ToString());
            }
        }
    }
}

效果图

到此这篇关于基于WPF实现ListBox拖动子项的文章就介绍到这了,更多相关WPF ListBox拖动子项内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文