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拖动子项内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论