动图演示:

背景:

一开始做功能的时候没有增加排序的索引(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# 拖拽列表顺序 | 拖拽合并分组 | 移除分组功能的更多相关文章

  1. 【UWP】拖拽列表项的排序功能实现

    在一些允许用户自定义栏目顺序的app(如:凤凰新闻.网易云音乐等),我们可以方便地拖拽列表项来完成列表的重新排序,进而完成对栏目顺序的重排.这个功能很人性化,而实现起来其实很简单(甚至都不用写什么后台 ...

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

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

  3. Android学习系列(11)--App列表之拖拽ListView(下)

    接着上篇Android学习系列(10)--App列表之拖拽ListView(上)我们继续实现ListView的拖拽效果. 7.重写onTouchEvent()方法.     在这个方法中我们主要是处理 ...

  4. Android学习系列(10)--App列表之拖拽ListView(上)

     研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.      鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...

  5. Android学习系列--App列表之拖拽ListView(下)

    接着上篇Android学习系列(10)--App列表之拖拽ListView(上)我们继续实现ListView的拖拽效果. 7.重写onTouchEvent()方法.     在这个方法中我们主要是处理 ...

  6. Android学习系列--App列表之拖拽ListView(上)

    研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.      鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. 一 ...

  7. Qt之股票组件-自选股--列表可以拖拽、右键常用菜单

    目录 一.开头嘴一嘴 二.效果展示 三.自选股列表 1.列表初始化 2.添加Item 3.右键菜单 4.拖拽Item 5.刷新数据 四.相关文章 原文链接:Qt之股票组件-自选股--列表可以拖拽.右键 ...

  8. 实现拖拽列表-微信小程序

    之前在网上搜索拖拽列表的实现时,发现了有好多的方法都是基于像素位置的计算实现的,这种方法要求列表元素的大小以及列表的位置有着非常严格的要求,修改和拓展起来非常的麻烦.于是我自己动手实现了一个基于页面元 ...

  9. 基于html5拖拽api实现列表的拖拽排序

    基于html5拖拽api实现列表的拖拽排序 html代码: <ul ondrop="drop_handler(event);" ondragover="dragov ...

  10. WPF拖拽文件(拖入拖出),监控拖拽到哪个位置,类似百度网盘拖拽

    1.往wpf中拖文件 // xaml <Grid x:Name="grid_11" DragOver="Grid_11_DragOver" Drop=&q ...

随机推荐

  1. 从Vue2转换为Vue3

    方便的Vue2到Vue3生命周期映射直接来自Vue3 Composition API文档,我认为这是了解事物将如何变化以及如何使用它们的最有用的方法之一. beforeCreate -> use ...

  2. D365增加Model reference,解决does not designate a class or table编译错误问题

    当我们导入基础数据时,需要创建一些基本的Emplyee信息,当引用到HcmHireNewWorkerContract和HcmWorkerTransition时,提示如下错误: 'HcmHireNewW ...

  3. [Contract] web3.eth.getAccounts, web3.eth.getCoinbase 使用场景区别

    web3.eth.getAccounts() 返回节点控制的账号列表(Promise returns Array) web3.eth.getCoinbase() 返回挖矿奖励所归集的地址(Promis ...

  4. clickhouse数据操常见执行语句

    1.清空本地表数据 truncate table 数据库名.表名 :) select * from test_local; SELECT * FROM test_local Query id: ab1 ...

  5. 数据分析之pyecharts v1版本

    维护人员,感谢他们 https://github.com/chenjiandongx https://github.com/chfw https://github.com/kinegratii中文文档 ...

  6. SAP HANA计算视图

    Text. Text. Text. Text. Text. Text. Text. Text. Text. Text. 越来越多的SAP用户正在将SAP HANA实施为现有SAP BW的基础和数据库. ...

  7. Spark中的闭包引用和广播变量

    闭包引用 概念 所有编程语言都有闭包的概念,闭包就是在一个函数中引用了函数外的变量. Spark中,普通的变量是在Driver程序中创建的,RDD的计算是在分布式集群中的task程序上进行的.因此,当 ...

  8. 16、数据库加固-mongo 加固

    1.指定日志与数据库存放位置 在配置文件中设置指向目录位置 自建配置文件:vim /usr/local/mongodb/etc/mongodb.conf dbpath=/data/db logpath ...

  9. git checkout 命令图文详解

    目录 git checkout branchname (切换本地分支) 切换远程分支 放弃修改 git checkout . git checkout – filename git checkout ...

  10. Ubuntu20.04桌面版图文安装(超详细)

    参考文档: https://baijiahao.baidu.com/s?id=1670100505795119581&wfr=spider&for=pc https://mirrors ...