当前位置: 代码网 > it编程>编程语言>C# > 基于WPF实现ListBox拖动子项

基于WPF实现ListBox拖动子项

2024年05月15日 C# 我要评论
wpf 实现 listbox 拖动子项框架支持.net4 至 .net8;visual studio 2022;实现代码xaml 部分1)新增mainwindow.xaml代码如下:grid定义两列。

wpf 实现 listbox 拖动子项

框架支持.net4 至 .net8

visual studio 2022;

图片

实现代码

xaml 部分

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

  • grid 定义两列。
  • 第一列 listbox 控件,命名 listboxstart,原数据被拖动者。
  • canvas 画布,用于在拖动过程中呈献拖动项。
  • 第二列 listbox 控件,命名 listboxend,用于接收拖动者。
<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 代码如下:

  • itemsa 和 itemsb 是 observablecollection<string>,分别用于存储 listboxstart 和 listboxend 中的项。
  • listboxstart_previewmouseleftbuttondown 方法处理当在 listboxstart 按下鼠标左键时的 item 数据,标记拖放操作的开始。
  • findvisualparent 在可视树中查找元素。
  • getlistboxitemdata 获取选中项 listboxitem 的数据。
  • listboxstart_previewmouseleftbuttonup 处理当在 listboxstart 释放鼠标左键的事件执行实际的拖放操作。
  • listboxstart_previewmousemove 处理当在 listboxstart 移动鼠标时的事件在拖动过程中更新拖动的位置。
  • listboxend_drop 处理当将 listboxstart 拖动项放到 listboxend 的事件,将拖动项添加到 listboxend 的数据源中。
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拖动子项内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com