WinUI3入门16:Order自定义排序

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客

C#是我多年以来的业余爱好,新搞的东西能用C#的就用C#了。


        接上一篇继续研究排序问题。上一篇:WinUI3入门15:DataGrid排序-CSDN博客

        前一篇使用OrderBy对指定列排序,如果要同时对多列排序,或许可以用一串OrderBy来实现(因为OrderBy是稳定排序,如果相等,不会改变相对顺序)。

        但是首先写一串OrderBy相当繁琐,效果存在不确定性(依赖算法特性),其次多次排序性能可能存在问题,当然这都不是关键问题。

        关键问题是这不符合完全自定义这个目标。传统上(指C++)我们用传递一个比较函数(或函数对象)的方法来实现自定义的排序规则,在C#同样可以通过传递特定的接口来实现。

目录

一、Enumerable.Order 方法

二、ICompare

三、设计通用的比较接口


一、Enumerable.Order 方法

        ObservableCollection<>实现了IEnumerable<T> 接口,因此可以用Order方法进行排序。Order方法接受一个IComparer<T>参数:

public static System.Linq.IOrderedEnumerable<T> Order<T> (this System.Collections.Generic.IEnumerable<T> source, System.Collections.Generic.IComparer<T>? comparer);

        很明显这个ICompare<T>就是用作比较的方法,所以问题就归结为编写ICompare<T>。

二、ICompare<T>

        ICompare<T>要求如下:

public int Compare (T? x, T? y);

        这个我们看着很眼熟,返回值也很眼熟:0代表相等,大于0代表x>y,小于0代表x<y,跟我们传统的x-y是一样的。

三、设计通用的比较接口

        通常为了多列比较我们需要下面的信息:

  • 哪些列用作比较
  • 这些列的比较顺序(优先级)
  • 每个列的比较方法(字符串、数值、升序降序)

        因为这里是直接用属性比较,那么字符串还是数值是不需要额外记录的,所以要记住的就是列和升序降序,我们可以用下面的类来描述:

		public class SortColumn{public String name = "";public bool sortOrderAscending = true;//false Descending}

        再定义一个列表就可以描述列的顺序了:

		public List<SortColumn> sortColumns = new();

        现在我们考虑把描述规则放在一个类里,而具体的比较由类自身的方法来实现。理论上通过上一篇用的动态类型(PropertyInfo)处理是可以实现完美的通用比较类的,不过有时候自定义一下也没什么不好,可能更简单、更高效。

        整个通用部分如下:

	public interface IMyOrder<T> where T : IMyOrder<T>{int CompareTo(MyOrder<T> order, T tmp);}public class MyOrder<T> : System.Collections.Generic.IComparer<T> where T : IMyOrder<T> {public class SortColumn{public String name = "";public bool sortOrderAscending = true;//false Descending}public List<SortColumn> sortColumns = new();public MyOrder(){}//清除排序规则public void ClearSortColumn(){sortColumns.Clear();}//指定进行排序的列public void SetSortColumn(String colname){SortColumn? sortColumn = null;int index = -1;if (sortColumns.Count != 0){for (int i = 0; i < sortColumns.Count; ++i){SortColumn tmpColumn =sortColumns[i];if (tmpColumn.name == colname){sortColumn=tmpColumn;sortColumns.Remove(tmpColumn);index = i;}}}if (null == sortColumn){sortColumn = new SortColumn();sortColumn.name = colname;sortColumns.Add(sortColumn);}else{if (0 == index) sortColumn.sortOrderAscending = !sortColumn.sortOrderAscending;sortColumns.Insert(0, sortColumn);}}public int Compare(T? x, T? y){if(null==x && null==y)return 0;if (null == x) return -1;if(null==y)return 1;return x.CompareTo(this, y);}}

        前面定义了一个接口IMyOrder<T>用来由实际的数据实现比较函数。而MyOrder<T>的IComparer<T>的实现“public int Compare(T? x, T? y)”则调用IMyOrder<T>的CompareTo来实现真正的比较。

        最复杂的是SetSortColumn,要检查是否是已经存在的排序列,最新点击的排第一,如果连续点击第一个就改变正序逆序。

        数据那边则要增加对IMyOrder<T>的实现:

		public class Data : INotifyPropertyChanged, IMyOrder<Data>{。。。。。。public int CompareTo(MyOrder<Data> order,Data tmp){for (int i = 0; i < order.sortColumns.Count; ++i){int ret = 0;MyOrder<Data>.SortColumn sortColumn = order.sortColumns[i];if (sortColumn.name == "Dir") ret = _dir.CompareTo(tmp._dir);if (sortColumn.name == "File") ret = _file.CompareTo(tmp._file);if (sortColumn.name == "Ext") ret = _ext.CompareTo(tmp._ext);if (sortColumn.name == "Type") ret = _type.CompareTo(tmp._type);if (sortColumn.name == "Encode") ret = _encode.CompareTo(tmp._encode);if (sortColumn.name == "BOM") ret = _bom.CompareTo(tmp._bom);if (sortColumn.name == "CR") ret = _cr.CompareTo(tmp._cr);if (sortColumn.name == "CRLF") ret = _crlf.CompareTo(tmp._crlf);if (sortColumn.name == "LF") ret = _lf.CompareTo(tmp._lf);if (sortColumn.name == "Length") ret = _length.CompareTo(tmp._length);if (sortColumn.name == "State") ret = _state.CompareTo(tmp._state);if (!sortColumn.sortOrderAscending) ret = -ret;if (0 != ret) return ret;}return 0;}}

        主代码中的主要过程:

		MyOrder<Data> myOrder = new();//Sorting事件添加排序列myOrder.SetSortColumn(e.Column.Header.ToString());排序newdatas = datas.Order(myOrder);


(这里是文档结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913564.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 面向对象三大特性详解:封装、继承与多态,掌握OOP核心思想

作为一名Java开发工程师&#xff0c;你一定知道&#xff0c;封装&#xff08;Encapsulation&#xff09;、继承&#xff08;Inheritance&#xff09;和多态&#xff08;Polymorphism&#xff09; 是面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;的三大…

WPS中配置MathType教程

项目场景&#xff1a;在WPS中使用MathType问题描述&#xff1a;MathPage.wll或MathType.dll文件找不到问题原因分析&#xff1a;在C盘wps中的startup中有mathpage.wll,但配置不可用而我的WPS安装在E盘&#xff0c;并且桌面图标启动路径也是E盘路径下的WPS路径&#xff0c;所以不…

基于模板设计模式开发优惠券推送功能以及对过期优惠卷进行定时清理

1.模板设计模式&#xff1a;模板设计模式是一种常见的设计模式&#xff0c;主要作用是对 具体操作的 共有代码块进行提取&#xff0c;提升代码复用性。那么说道代码复用性&#xff0c;首先想到的是抽象类而不是接口。因为抽象类的本质就是为了代码复用&#xff0c;抽象类既可以…

对象的finalization机制Test1

Java语言提供了对象终止(finalization)机制来允许开发人员自定义对象被销毁之前的处理逻辑。当垃圾回收器发现没有引用指向一个对象时&#xff0c;通常接下来要做的就是垃圾回收&#xff0c;即清除该对象&#xff0c;而finalization机制使得在清除此对象之前&#xff0c;总会先…

RJ45 连接器(水晶头)的引脚定义

RJ45连接器核心定义 【】物理结构 8个金属触点&#xff08;Pin 1至Pin 8&#xff09;的透明塑料插头&#xff0c;带塑料卡榫。 引脚编号规则 卡榫朝下&#xff0c;金属触点面向自己时&#xff1a; 最左侧为 Pin 1 最右侧为 Pin 8 顺序&#xff1a;Pin 1 → Pin 2 → Pin 3 → P…

小架构step系列08:logback.xml的配置

1 概述 logback.xml配置文件的详细配置&#xff0c;很多地方都说得比较细&#xff0c;本文主要从几个重点来看一下原理&#xff0c;了解原理能够帮助确定哪些应该配置&#xff0c;以及如何配置。 logback.xml是为打印日志服务的&#xff0c;打印的内容一般打印到控制台(Conso…

STM32中SPI协议详解

前言 在嵌入式系统中&#xff0c;设备间的数据传输协议多种多样&#xff0c;SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外设接口&#xff09;凭借其高速、全双工、易用性等特点&#xff0c;成为连接STM32与高速外设&#xff08;如OLED屏、Flash芯片、AD转换器…

TypeScript 接口全解析:从基础到高级应用

TypeScript 接口全解析&#xff1a;从基础到高级应用在 TypeScript 中&#xff0c;接口是定义数据结构和行为规范的强大工具&#xff0c;它能够显著提升代码的可读性、可维护性和类型安全性。本文将全面讲解 TypeScript 接口的相关知识点&#xff0c;从基础语法到高级特性&…

主存(DRAM)是什么?

主存&#xff08;DRAM&#xff09;是什么&#xff1f; 主存&#xff08;DRAM&#xff09;详解 主存&#xff08;Main Memory&#xff09; 通常由 DRAM&#xff08;Dynamic Random Access Memory&#xff0c;动态随机存取存储器&#xff09; 构成&#xff0c;是计算机系统中用于…

Python 机器学习核心入门与实战进阶 Day 6 - 模型保存与加载(joblib / pickle)

✅ 今日目标 掌握如何将训练好的模型持久化保存到文件熟悉两种主流保存方式&#xff1a;joblib 和 pickle加载模型并应用于新数据预测实现完整的“训练 → 保存 → 加载 → 预测”流程为后续部署做准备&#xff08;如 Flask、FastAPI&#xff09;&#x1f9f0; 一、模型保存工具…

【SigNoz部署安装】Ubuntu环境部署SigNoz:Docker容器化监控的全流程指南

文章目录前言1.关于SigNoz2.本地部署SigNoz3.SigNoz简单使用4. 安装内网穿透5.配置SigNoz公网地址6. 配置固定公网地址前言 在分布式架构主导的现代运维体系中&#xff0c;系统性能监控正面临范式变革的关键转折。当微服务架构遭遇服务雪崩、无服务器架构出现冷启动延迟等复杂…

NV298NV312美光固态闪存NW639NW640

美光固态闪存技术全景解析&#xff1a;从NV298到NW640的深度探索近年来&#xff0c;美光科技凭借其在3D NAND闪存技术上的持续突破&#xff0c;推出了多款备受市场关注的固态硬盘产品。本文将从技术评测、产品对比、市场趋势、用户反馈及应用场景等多个维度&#xff0c;深入剖析…

2025.07.04【服务器】|使用万兆网卡提升服务器间互联速度,实现快速数据传输

文章目录1. **万兆网卡概述**2. **为什么选择万兆网卡**3. **万兆网卡配置与安装**3.1 **安装网卡**3.2 **安装驱动程序**3.3 **检查网卡状态**4. **配置网络接口**4.1 **Linux 系统配置**4.2 **Windows 系统配置**5. **优化性能**5.1 **使用多线程传输**5.2 **开启 TCP/UDP 窗…

光伏发电量精准估算,提升投资效益

在光伏产业规模化发展进程中&#xff0c;准确估算光伏发电量是提升项目投资效益的关键环节。科学的发电量预测不仅能为项目可行性研究提供依据&#xff0c;更能在电站全生命周期内优化运营策略&#xff0c;实现投资回报最大化。基于多维度数据整合与智能算法构建的精准预测体系…

Linux的互斥锁、Linux的POSIX信号量(二值、计数)、RTOS的二值信号量

锁和信号量最大的区别就是:锁严格要求 “谁占用谁释放”,而信号量允许 “一个任务 / 线程释放,另一个任务 / 线程获取”。 特性互斥锁(Mutex)POSIX 信号量(Semaphore)初始状态初始为 “锁定”(PTHREAD_MUTEX_INITIALIZER),需显式获取(pthread_mutex_lock)。初始值可…

基于Java+SpringBoot 协同过滤算法私人诊所管理系统

源码编号&#xff1a;S607源码名称&#xff1a;基于SpringBoot5的协同过滤算法的私人诊所管理系统用户类型&#xff1a;双角色&#xff0c;患者、医生、管理员数据库表数量&#xff1a;15 张表主要技术&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven运行环境&#xff1…

什么是DINO?

DINO 是一个由 Meta AI (当时的 Facebook AI) 在 2021 年提出的自监督学习框架&#xff0c;其全称是 “self-DIstillation with NO labels”&#xff0c;直译为“无标签的自我蒸馏”。这个名字精准地概括了它的核心思想。 DINO 的出现是一个里程碑&#xff0c;因为它首次有力地…

如何在 Android Framework层面控制高通(Qualcomm)芯片的 CPU 和 GPU。

如何在 Android Framework层面控制高通&#xff08;Qualcomm&#xff09;芯片的 CPU 和 GPU。 参考&#xff1a;https://blog.csdn.net/YoungHong1992/article/details/117047839?utm_source%20%20uc_fansmsg 作为一名 Framework 开发者&#xff0c;您拥有系统级的权限&#…

程序员在线接单

十年Java全栈工程师在线接单Java程序代做&#xff0c;兼职接单&#xff0c;系统代做&#xff0c;二次开发&#xff0c;网站开发部署&#xff0c;项目合作&#xff0c;商业项目承包 全栈开发&#xff0c;支持定制各种管理系统、小程序 商用或个人使用等项目都接 服务二: Java调试…

Python 异步爬虫(aiohttp)高效抓取新闻数据

一、异步爬虫的优势 在传统的同步爬虫中&#xff0c;爬虫在发送请求后会阻塞等待服务器响应&#xff0c;直到收到响应后才会继续执行后续操作。这种模式在面对大量请求时&#xff0c;会导致大量的时间浪费在等待响应上&#xff0c;爬取效率较低。而异步爬虫则等待可以在服务器…