c# 拖拽列表顺序 | 拖拽合并分组 | 移除分组功能
动图演示:

背景:
一开始做功能的时候没有增加排序的索引(sort-index),后来要求做拖拽排序功能;所以写了这个不需要初始排序就可以完成的拖拽功能;如果是table表格排序逻辑和这个相似,这里拿这个angular框架的树形菜单来做例子;
核心逻辑:
1,查询列表需要通过多字段进行排序如:SortIndex(新创建的字段,默认值为0),创建时间,Id
2,编写拖拽逻辑,同级别的互相移动。移动后修改全部SortIndex(索引字段);
3,不同级别的相互合并或拆分(修改父Id即可)。移动后修改全部SortIndex(索引字段);
代码展示:
前端方法:
<nz-tree #studentgroupTree [nzData]="treeData" nzShowIcon [nzSearchValue]="searchTreeNodeValue" (nzSearchValueChange)="searchTreeNode($event)"
nzDraggable nzBlockNode [nzBeforeDrop]="beforeDrop" (nzOnDrop)="onDropTreeNode($event)" (nzClick)="clickTreeNode()" >
</nz-tree>
treeData就是调用后台查询的方法返回的数据集合;
其中 [nzBeforeDrop]表示拖拽前的验证;[onDropTreeNode]表示拖拽的方法,在ts或js中调用后台方法;

后端查询方法:
public object GetTreeData()
{
List<Organization> allPermissionOrgList = new List<Organization>() { }; allPermissionOrgList = allPermissionOrgList.OrderBy(t => t.SequenceNo).ThenBy(t => t.CreatedTime).ThenBy(t => t.Id).ToList(); return allPermissionOrgList;
}
排序顺序尽量按照先索引然后创建时间其次ID的排序;
后端拖拽方法:
/// <summary>
/// 移动学员分组
/// </summary>
/// <param name="dragNodeid">拖拽对象</param>
/// <param name="nodeid">目标对象</param>
/// <param name="pos">见上文描述</param>
/// <returns></returns>
public virtual async Task<OperationResult> MoveStudentTreeNode(int dragNodeid, int nodeid, int pos)
{
var dragNode = OrganizationRepository.Get(dragNodeid);
if (dragNode == null)
{
return new OperationResult(OperationResultType.NoChanged);
}
var node = OrganizationRepository.Get(nodeid);
if (node == null)
{
return new OperationResult(OperationResultType.NoChanged);
} List<Organization> GroupList = new List<Organization>(); var OrganizationsList = Organizations.Where(x => x.OrganizationType == 1 && x.DeletedTime == null);
if (node.ParentId != null)
{//有父级,表示本身是子级
GroupList = OrganizationsList.Where(x => x.ParentId == node.ParentId).ToList();
}
else if (node.ParentId == null && pos == 0)
{//没有父级,并且pos等于0 代表拖拽到中间位置了
GroupList = OrganizationsList.Where(x => x.ParentId == node.Id).ToList();
}
else
{//没有父级,表示本身是父级
GroupList = OrganizationsList.Where(x => x.ParentId == null).ToList();
}
GroupList = GroupList.Distinct().OrderBy(t => t.ParentId).ThenBy(t => t.SequenceNo).ThenBy(t => t.Id).ToList(); List<Organization> editedNodeList = new List<Organization>();
string belongId = string.Empty;
switch (pos)
{
case 0:
dragNode.ParentId = node.Id;
belongId = node.Path.Split(',', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
if (!string.IsNullOrEmpty(belongId))
await UserRepository.QueryAsNoTracking().Where(x => x.BelongToRootId == dragNode.Id).UpdateFromQueryAsync(x => new User { BelongToRootId = Convert.ToInt32(belongId) });
SetTreePath(dragNode);
GroupList.Insert(0, dragNode);
for (int i = 0; i < GroupList.Count; i++)
{
var item = GroupList[i];
item.SequenceNo = i + 1;
editedNodeList.Add(item);
}
break;
case -1:
case 1:
if (dragNode.ParentId == node.ParentId)
{//如果是同一目录拖拽
GroupList.Remove(dragNode); var itemIndex = GroupList.IndexOf(node);
if (pos == -1)
GroupList.Insert(itemIndex + 0, dragNode);
else
GroupList.Insert(itemIndex + 1, dragNode); for (int i = 0; i < GroupList.Count; i++)
{
var item = GroupList[i];
item.SequenceNo = i + 1;
editedNodeList.Add(item);
}
}
else
{//如果是不同目录拖拽
dragNode.ParentId = node.ParentId;
belongId = node.Path.Split(',', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
if (!string.IsNullOrEmpty(belongId))
await UserRepository.QueryAsNoTracking().Where(x => x.BelongToRootId == dragNode.Id).UpdateFromQueryAsync(x => new User { BelongToRootId = Convert.ToInt32(belongId) });
//UpdateBelongToRootIds(dragNode.Id, Convert.ToInt32(belongId));
SetTreePath(dragNode); var itemIndex = GroupList.IndexOf(node);
if (pos == -1)
GroupList.Insert(itemIndex + 0, dragNode);
else
GroupList.Insert(itemIndex + 1, dragNode); for (int i = 0; i < GroupList.Count; i++)
{
var item = GroupList[i];
item.SequenceNo = i + 1;
editedNodeList.Add(item);
}
}
break;
default:
break;
}
if (editedNodeList.Count > 0)
await OrganizationRepository.UpdateAsync(GroupList.ToArray());
return new OperationResult(OperationResultType.NoChanged); }
结语:
整体核心代码就是拖拽方法那里,感觉写的还是比较通用的。如有疑问,欢迎评论。最后祝大家中秋国庆节日快乐;
c# 拖拽列表顺序 | 拖拽合并分组 | 移除分组功能的更多相关文章
- 【UWP】拖拽列表项的排序功能实现
在一些允许用户自定义栏目顺序的app(如:凤凰新闻.网易云音乐等),我们可以方便地拖拽列表项来完成列表的重新排序,进而完成对栏目顺序的重排.这个功能很人性化,而实现起来其实很简单(甚至都不用写什么后台 ...
- Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现
Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用L ...
- Android学习系列(11)--App列表之拖拽ListView(下)
接着上篇Android学习系列(10)--App列表之拖拽ListView(上)我们继续实现ListView的拖拽效果. 7.重写onTouchEvent()方法. 在这个方法中我们主要是处理 ...
- Android学习系列(10)--App列表之拖拽ListView(上)
研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨. 鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...
- Android学习系列--App列表之拖拽ListView(下)
接着上篇Android学习系列(10)--App列表之拖拽ListView(上)我们继续实现ListView的拖拽效果. 7.重写onTouchEvent()方法. 在这个方法中我们主要是处理 ...
- Android学习系列--App列表之拖拽ListView(上)
研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨. 鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. 一 ...
- Qt之股票组件-自选股--列表可以拖拽、右键常用菜单
目录 一.开头嘴一嘴 二.效果展示 三.自选股列表 1.列表初始化 2.添加Item 3.右键菜单 4.拖拽Item 5.刷新数据 四.相关文章 原文链接:Qt之股票组件-自选股--列表可以拖拽.右键 ...
- 实现拖拽列表-微信小程序
之前在网上搜索拖拽列表的实现时,发现了有好多的方法都是基于像素位置的计算实现的,这种方法要求列表元素的大小以及列表的位置有着非常严格的要求,修改和拓展起来非常的麻烦.于是我自己动手实现了一个基于页面元 ...
- 基于html5拖拽api实现列表的拖拽排序
基于html5拖拽api实现列表的拖拽排序 html代码: <ul ondrop="drop_handler(event);" ondragover="dragov ...
- WPF拖拽文件(拖入拖出),监控拖拽到哪个位置,类似百度网盘拖拽
1.往wpf中拖文件 // xaml <Grid x:Name="grid_11" DragOver="Grid_11_DragOver" Drop=&q ...
随机推荐
- 很强!4.7k star,推荐一款Python工具,可实现自动化操作!!
1.介绍 在日常工作中,肯定会遇到一些重复性的工作,不管是点击某个按钮.写东西,打印东西,还是复制粘贴拷贝资料之类的,需要进行大量的重复操作.按键精灵大家都听说过,传统的方式,大家可以使用按键精灵将操 ...
- 力扣520(java)-检测大写字母(简单)
题目: 我们定义,在以下情况时,单词的大写用法是正确的: 1.全部字母都是大写,比如 "USA" .2.单词中所有字母都不是大写,比如 "leetcode" . ...
- 力扣396(java)-旋转数组(中等)
题目: 给定一个长度为 n 的整数数组 nums . 假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为: F(k) = 0 * arrk[0 ...
- 巧用API网关构建大型应用体系架构
简介: 近期阿里云重磅发布了BizWorks一体化的云原生应用的开发和运营平台,内置阿里巴巴业务中台构建的最佳技术实践.它已经将API网关作为关键组件融入其中,并且基于API网关为用户提供能力开放平台 ...
- 携手数字人、数字空间、XR平台,阿里云与伙伴共同建设“新视界”
简介:2022阿里云视觉计算私享会:加速虚拟与现实的交互. 引言:2022年互联网行业里XR.数字孪生.虚拟现实等领域再次"翻红".新旧概念频出,不少人相信这些技术将给当下的互联 ...
- dotnet 使用 IndentedTextWriter 辅助生成代码时生成带缩进的内容
随着源代码生成的越来越多的应用,自然也遇到了越来越多开发上的坑,例如源代码的缩进是一个绕不过去的问题.如果源代码生成是人类可见的代码,我期望生成的代码最好是比较符合人类编写代码的规范.为了能让人类在阅 ...
- 用 SetWindowPos 方法设置一个停止响应的窗口将卡调用方
我使用 User32 的 SetWindowPos 方法去设置一个跨进程的窗口,这个窗口是停止响应的,将让调用的 SetWindowPos 方法卡住,不继续执行逻辑.通过堆栈分析是卡在 NtUserS ...
- 使用sqlcmd命令行执行.sql文件
用微软自带的sqlcmd命令行工具,可以执行导入.以SQL Server 2016版本为例: 第一步:Win+R 键入:cmd 命令,开启命令行工具: 第二步:键入:sqlcmd -S . -U sa ...
- 深入理解Python协程:从基础到实战
title: 深入理解Python协程:从基础到实战 date: 2024/4/27 16:48:43 updated: 2024/4/27 16:48:43 categories: 后端开发 tag ...
- CF620E New Year Tree (线段树维护 dfs 序)
CF620E New Year Tree 题意:给出一棵 n 个节点的树,根节点为 1.每个节点上有一种颜色 ci.m 次操作.操作有两种: 1 u c:将以 u 为根的子树上的所有节点的颜色改为 ...