实现目标,在一个ListBox中选择一个子项进行拖拽到另一个ListBox中,拖拽到某一子项区域进行替换

下面是axaml代码

 1  <ListBox
2 Name="consumableListBox"
3 Margin="5"
4 ItemsSource="{Binding ConsumableList}"
5 SelectionMode="Single">
6 <ListBox.ItemTemplate>
7 <DataTemplate>
8 <StackPanel Margin="5,5,5,0">
9 <Border
10 Width="160"
11 Height="100"
12 Margin="0,0,0,5"
13 HorizontalAlignment="Center"
14 Background="Red"
15 CornerRadius="5" />
16 <TextBlock HorizontalAlignment="Center" Text="{Binding}" />
17 </StackPanel>
18 </DataTemplate>
19 </ListBox.ItemTemplate>
20 </ListBox>

源ListBox

<ListBox
Name="platePositionListBox"
Margin="5"
ItemsSource="{Binding PlatePositionList}"
SelectionMode="Single">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5,5,5,0">
<Border
Width="160"
Height="100"
Margin="0,0,0,5"
HorizontalAlignment="Center"
Background="Red"
CornerRadius="5" />
<TextBlock HorizontalAlignment="Center" Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

目标ListBox

给源ListBox添加指针移动事件

 1 private void SourceList_PointerMoved(object sender, PointerEventArgs e)
2 {
3 // 当拖拽操作开始时,在源列表中开始拖拽
4 if (e.GetCurrentPoint(consumableListBox).Properties.IsLeftButtonPressed)
5 {
6 DataObject dataObject = new DataObject();
7 dataObject.Set("dataObject", consumableListBox.SelectedItem);
8 DragDrop.DoDragDrop(e, dataObject, DragDropEffects.Move);
9 }
10 }

源ListBox指针移动

将目标ListBox设为允许拖入

DragDrop.SetAllowDrop(platePositionListBox, true);

由于ListBox没有DropEvent事件,需要进行添加事件

platePositionListBox.AddHandler(DragDrop.DropEvent, PlatePositionListBox_DropEvent, RoutingStrategies.Bubble | RoutingStrategies.Direct);

对应事件实现,其中需要获取到需要替换的项的下标,本处是通过定位进行计算

 1 private void PlatePositionListBox_DropEvent(object? sender, DragEventArgs e)
2 {
3 var a = e.Data.Get("dataObject");
4 if (e.Data.Contains("dataObject") && a != null)
5 {
6 var targetIndex = GetDropTargetIndex(platePositionListBox, e.GetPosition(platePositionListBox));
7 if (targetIndex >= 0)
8 {
9 if (this.DataContext is PlanViewModel viewModel)
10 {
11 viewModel.PlatePositionList.RemoveAt(targetIndex);
12 viewModel.PlatePositionList.Insert(targetIndex, a.ToString());
13 }
14 }
15 }
16 }
17
18
19 //获取目标项下标
20 private int GetDropTargetIndex(ListBox targetListBox, Avalonia.Point position)
21 {
22 var itemsControl = targetListBox;
23
24 var itemsPoint = GetAllItemDistances(targetListBox);
25 var firstItemPanel = (StackPanel)Avalonia.VisualTree.VisualExtensions.FindDescendantOfType<StackPanel>(itemsControl);
26 var itemContainer = (Control)firstItemPanel;
27 var firstItemBounds = itemContainer.Bounds;
28 var items = itemsControl.Items;
29 var y = firstItemBounds.Y;
30 for (int i = 0; i < items.Count; i++)
31 {
32 if (itemsPoint[i].Index == -1)
33 {
34 continue;
35 }
36 if (position.Y >= itemsPoint[i].DistanceToTop && position.Y <= itemsPoint[i].DistanceToTop + firstItemBounds.Height)
37 {
38 return i;
39 }
40 }
41 return items.Count;
42 }
43
44 //获取目标ListBox的项距离顶部边框的距离,如果未呈现到画面上,下标设为-1
45 private List<ItemCoordinates> GetAllItemDistances(ListBox listBox)
46 {
47 var itemCoordinatesList = new List<ItemCoordinates>();
48 var items = listBox.Items;
49 var scrollViewer = listBox.FindDescendantOfType<ScrollViewer>();
50 var topOffset = scrollViewer.Offset.Y;
51
52 for (int i = 0; i < items.Count; i++)
53 {
54 var itemContainer = listBox.ItemContainerGenerator.ContainerFromIndex(i) as Control;
55 if (itemContainer != null)
56 {
57 var itemBounds = itemContainer.Bounds;
58 var distanceToTop = itemBounds.Top - topOffset;
59 itemCoordinatesList.Add(new ItemCoordinates(i, distanceToTop));
60 }
61 else
62 {
63 itemCoordinatesList.Add(new ItemCoordinates(-1, -999));
64 }
65 }
66 return itemCoordinatesList;
67 }

具体实现

最终效果:

初始画面

拖拽后:

Avalonia 列表拖拽替换的更多相关文章

  1. ListView列表拖拽排序

    ListView列表拖拽排序能够參考Android源代码下的Music播放列表,他是能够拖拽的,源代码在[packages/apps/Music下的TouchInterceptor.java下]. 首 ...

  2. Android滑动列表(拖拽,左滑删除,右滑完成)功能实现(2)

    ItemTouchHelper类 之前我们实现了滑动列表的一些基本功能,为了实现更多的效果,我们来仔细看一下ItemTouchHelper中的类: ItemTouchHelper.SimpleCall ...

  3. vue列表拖拽排序功能实现

    1.实现目标:目标是输入一个数组,生成一个列表:通过拖拽排序,拖拽结束后输出一个经过排序的数组. 2.实现思路: 2.1是使用HTML5的drag功能来实现,每次拖拽时直接操作Dom节点排序,拖拽结束 ...

  4. dev gridview 单元格值拖拽替换

    public class GridViewDropCell { //dvginfo根据鼠标点击的x.y坐标获取该点的相关信息 private GridHitInfo downHitInfo; priv ...

  5. Android滑动列表(拖拽,左滑删除,右滑完成)功能实现(1)

    场景: 近期做的TODO APP需要在主页添加一个功能,就是可以左滑删除,右滑完成.看了一下当前其他人做的例如仿探探式的效果,核心功能基本一样,但是和我预想的还是有少量区别,于是干脆自己重头学一遍如何 ...

  6. vue列表拖拽组件 vue-dragging

    安装 $ npm install awe-dnd --save 应用 在main.js中,通过Vue.use导入插件 import VueDND from 'awe-dnd' Vue.use(VueD ...

  7. jQuery图片列表拖拽排序布局

    在线演示 本地下载

  8. Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现

    Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用L ...

  9. html5 Sortable.js 拖拽排序源码分析

    最近公司项目经常用到一个拖拽 Sortable.js插件,所以有空的时候看了 Sortable.js 源码,总共1300多行这样,写的挺完美的.   本帖属于原创,转载请出名出处. 官网http:// ...

  10. sortable.js 拖拽排序及配置项说明

    // 拖动排序 $(function() { /*排序*/ //排序 // Simple list ]; new Sortable(list, { group: "name", a ...

随机推荐

  1. CF1477F Nezzar and Chocolate Bars 题解

    题意: 有一根长为 \(1\) 的巧克力,已经被切了 \(m-1\) 刀被分成 \(m\) 分,接下来每次在整根长度为 \(1\) 的巧克力上均匀随机一个点切一刀,求每一小段巧克力长度均小于一个给定值 ...

  2. plotly 坐标轴范围截断rangebreaks使用的一个注意点

    plotly坐标轴截断混合设置且指定设置截断时间的时候需要注意先后顺序 大范围的时间要在小范围的时间前设置,比如日内时间的截断要设置在日期截断的后面 同范围的规则截断要在指定截断前设置,对日期的截断, ...

  3. 2022-03-09:我们正在玩一个猜数游戏,游戏规则如下: 我从 1 到 n 之间选择一个数字。 你来猜我选了哪个数字。 如果你猜到正确的数字,就会 赢得游戏 。 如果你猜错了,那么我会告诉你,我选

    2022-03-09:我们正在玩一个猜数游戏,游戏规则如下: 我从 1 到 n 之间选择一个数字. 你来猜我选了哪个数字. 如果你猜到正确的数字,就会 赢得游戏 . 如果你猜错了,那么我会告诉你,我选 ...

  4. nodejs 入门基本操作

    操作fs模块 const path = require("path"); const fs = require("fs"); /* 相对路径是命令窗口执行的目录 ...

  5. lec-1-Deep Reinforcement Learning, Decision Making, and Control

    What is RL 基于学习的决策的数学形式 从经验中学习决策和控制的方法 Why should we study this now 深度神经网络特征方法 强化学习的提升 计算能力的提升 我们还需要 ...

  6. TLS 加速技术:Intel QuickAssist Technology(QAT)解决方案

    作者:vivo 互联网服务器团队- Ye Feng 本文介绍了 Intel QAT 技术方案,通过Multi-Buffer技术和QAT硬件加速卡的两种方式实现对TLS的加速 一.背景 当前 TLS 已 ...

  7. AcWing 3956. 截断数组

    给定一个长度为 n 的数组 a1,a2,-,an. 现在,要将该数组从中间截断,得到三个非空子数组. 要求,三个子数组内各元素之和都相等. 请问,共有多少种不同的截断方法? 输入格式 第一行包含整数 ...

  8. celery笔记二之建立celery项目、配置及几种加载方式

    本文首发于公众号:Hunter后端 原文链接:celery笔记二之建立celery项目.配置及几种加载方式 接下来我们创建一个 celery 项目,文件夹及目录如下: proj/__init__.py ...

  9. .net 温故知新【11】:Asp.Net Core WebAPI 入门使用及介绍

    在Asp.Net Core 上面由于现在前后端分离已经是趋势,所以asp.net core MVC用的没有那么多,主要以WebApi作为学习目标. 一.创建一个WebApi项目 我使用的是VS2022 ...

  10. Linux下程序时间消耗监控与统计

    良好的计时器可帮助程序开发人员确定程序的性能瓶颈,或对不同算法进行性能比较.但要精确测量程序的运行时间并不容易,因为进程切换.中断.共享的多用户.网络流量.高速缓存访问及转移预测等因素都会对程序计时产 ...