当前位置: 首页 > news >正文

C#ListView的单元格支持添加基本及自定义任意控件

功能说明

使用ListView时,希望可以在单元格显示图片或其他控件,发现原生的ListView不支持,于是通过拓展,实现ListView可以显示任意控件的功能,效果如下:
在这里插入图片描述

实现方法

本来想着在单元格里面实现控件的自绘的,但是没找到办法,最后是通过在单元格的表面显示对应控件的,浮于表面达到目的。
实现要点如下:

  • ListView需要设置OwnerDraw=true,并重载自绘函数OnDrawColumnHeaderOnDrawItemOnDrawSubItem
  • 支持按单元格添加对应的控件,其Parent设置为列表ListView
  • 列表界面调整后,包括大小、列表头、滚动等,需重新绘制单元格的控件

实现源码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace MyListView.Ui
{#region ListViewExpublic class ListViewEx : ListView{#region 内部属性/// <summary>/// 存放单元格控件/// </summary>List<Control> _CellControls = new List<Control>();/// <summary>/// 界面是否发生变化/// </summary>bool IsViewChanged { get; set; }#endregion#region 方法/// <summary>/// 构造函数/// </summary>public ListViewEx(){#region 初始化#endregion#region 事件this.ColumnReordered += ColumnWidthChangedHandler;this.ColumnWidthChanged += ColumnWidthChangedHandler;#endregion}/// <summary>/// 添加控件/// </summary>/// <typeparam name="T"></typeparam>/// <param name="row"></param>/// <param name="col"></param>/// <param name="c"></param>/// <returns></returns>public T Add<T>(int row, int col, T c) where T : Control{if(row >= this.Items.Count || col >= this.Columns.Count){return null;}var index = (row * this.Columns.Count) + col;for (var i = _CellControls.Count; i <= index; i++){_CellControls.Add(null);}var oc = _CellControls[index];if (oc != null){oc.Dispose();}OwnerDraw = true;IsViewChanged = true;c.Parent = this;_CellControls[index] = c;return c;}/// <summary>/// 设置行高度/// </summary>/// <param name="height"></param>public void SetItemHeight(int height){if(this.SmallImageList == null){this.SmallImageList = new ImageList();}this.SmallImageList.ImageSize = new Size(1, height);}#endregion#region 内部函数void ColumnWidthChangedHandler(object s, EventArgs e){IsViewChanged = true;}/// <summary>/// 显示控件到目标单元格/// </summary>/// <param name="c"></param>/// <param name="item"></param>void ShowCellControl(Control c, ListViewItem.ListViewSubItem item){int margin = 2;c.Text = item.Text;c.Visible = true;c.Bounds = new Rectangle(item.Bounds.X + margin,item.Bounds.Top + margin,item.Bounds.Width - 2 * margin,item.Bounds.Height - 2 * margin);}/// <summary>/// 显示单元格控件/// </summary>/// <param name="e"></param>/// <returns></returns>Control GetCellControl(DrawListViewSubItemEventArgs e){Control c = null;#region 获取控件var index = (e.ItemIndex * this.Columns.Count) + e.ColumnIndex;if (index >= _CellControls.Count){return null;}c = _CellControls[index];#endregionreturn c;}protected override void WndProc(ref Message m){#region 事件定义const int WM_SIZE = 0x0005;const int WM_PAINT = 0x000F;const int WM_HSCROLL = 0x114;const int WM_VSCROLL = 0x115;const int WM_MOUSEWHEEL = 0x020A;#endregion#region 重绘显示控件if (m.Msg == WM_PAINT && IsViewChanged){if(this.Columns.Count > 0){for (var i = 0; i < _CellControls.Count; i++){var cell_control = _CellControls[i];if (cell_control == null){continue;}cell_control.Visible = false;var row = i / this.Columns.Count;var col = i % this.Columns.Count;if(row >= Items.Count || col >= this.Columns.Count){continue;}var item = this.Items[row];if(item.Bounds.Y < 0 || item.Bounds.Y >= this.Height){continue;}if(item.SubItems[col].Bounds.X < 0 || item.SubItems[col].Bounds.X >= this.Width){continue;}ShowCellControl(cell_control, item.SubItems[col]);}IsViewChanged = false;}}else if(m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_SIZE){IsViewChanged = true;}#endregionbase.WndProc(ref m);}protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e){e.DrawDefault = true;}protected override void OnDrawItem(DrawListViewItemEventArgs e){// 已经在OnDrawSubItem处理过了// e.DrawText(TextFormatFlags.Default);}protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e){if(GetCellControl(e) != null){return;}else{e.DrawDefault = true;}}#endregion}#endregion
}

测试代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace MyListView
{public partial class Form1 : Form{#region 函数public Form1(){#region 布局初始化InitializeComponent();var lv = new Ui.ListViewEx(){Dock = DockStyle.Fill,View = View.Details,GridLines = true,};this.Controls.Add(lv);var headers = new string[] { "序号", "名称", "年龄", "住址", "荣誉", "岗位", "头像" };foreach(var v in headers){lv.Columns.Add(v, 100, HorizontalAlignment.Center);}lv.SetItemHeight(40);for(var i=0; i<50; i++){var lvi = lv.Items.Add($"数据{i + 1}");for(var j=1; j<lv.Columns.Count; j++){lvi.SubItems.Add($"数据{i + 1}-{j}");switch(j){case 1:lv.Add(i, j, new Label());break;case 2:lv.Add(i, j, new Button());break;case 3:lv.Add(i, j, new TextBox(){Font = new Font("宋体", 18)});break;case 4:lv.Add(i, j, new ComboBox(){Font = new Font("宋体", 18)});break;case 6:{var pic = lv.Add(i, j, new PictureBox());pic.Image = LoadImage($"logo{i%7}.jpg");pic.SizeMode = PictureBoxSizeMode.StretchImage;}break;}}}#endregion}Image LoadImage(string name){var file = Path.GetFullPath(Path.Combine(@"..\..\Data\IMG", name));if(!File.Exists(file)){return null;}return Image.FromFile(file);}#endregion}
}

相关文章:

C#ListView的单元格支持添加基本及自定义任意控件

功能说明 使用ListView时&#xff0c;希望可以在单元格显示图片或其他控件&#xff0c;发现原生的ListView不支持&#xff0c;于是通过拓展&#xff0c;实现ListView可以显示任意控件的功能&#xff0c;效果如下&#xff1a; 实现方法 本来想着在单元格里面实现控件的自绘的…...

数据库选型实践:如何避开分库分表痛点 | OceanBase用户实践

随着企业业务的不断发展&#xff0c;数据量往往呈现出快速的增长趋势。使用MySQL的用户面对这种增长&#xff0c;普遍选择采用分库分表技术作为应对方案。然而&#xff0c;这一方案常在后期会遇到很多痛点。 分库分表的痛点 痛点 1&#xff1a;难以保证数据一致性。由于分库分…...

3个火火火的AI项目,开源了!

友友们&#xff0c;今天我要给你们安利三个超酷的开源项目&#xff0c;它们都和AI有关&#xff0c;而且每一个都能让你的日常生活变得更加有趣和便捷&#xff01;(最近AI绘图又又超神了&#xff0c;分享以下美图养眼) 01 字节出品&#xff0c;文字转语音Seed-TTS 字节推出了一…...

算法 | 子集数排列树满m叉树二分搜索归并排序快速排序

子集树&#xff1a;O(2^n) 一个序列的所有子集为2^n&#xff0c;即可看成具有2^n个叶节点的满二叉树 int backtrack(int k) //k表示扩展结点在解空间树中所处的层次 {if(k>n) //n标识问题的规模output(x); //x是存放当前解的一维数组if(constraint(k)…...

SpringBoot配置第三方专业缓存技术jetcache方法缓存方案

jetcache方法缓存 我们可以给每个方法配置缓存方案 JetCache 是一个基于 Java 的缓存库&#xff0c;支持多种缓存方案和缓存策略&#xff0c;主要用于提升应用程序的性能和响应速度。它提供了多种缓存模式和特性&#xff0c;可以根据需求选择合适的缓存方案。 JetCache 的主…...

游戏开发丨基于PyGame的消消乐小游戏

文章目录 写在前面PyGame消消乐注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame实现喜羊羊与灰太狼版消消乐小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700193 实验环境 python3.11及以上pycharmpygame 安装pygame…...

软件项目管理概述

1.什么是项目&#xff1f; 2.项目管理的定义 3.项目管理的本质 4.项目成功的标志 5.项目管理的基本方法 6.项目的生命周期&#xff08;启动 计划 执行 控制 结束&#xff09; 7.结合生活中的某件事&#xff0c;谈谈项目管理的作用 项目管理在日常生活中扮演着重要的角色&…...

FastAdmin后台开发框架 lang 任意文件读取漏洞复现

0x01 产品简介 FastAdmin是一款基于PHPBootstrap的开源后台框架&#xff0c;专为开发者精心打造。它基于ThinkPHP和Bootstrap两大主流技术构建&#xff0c;拥有完善的权限管理系统和一键生成CRUD等强大功能。FastAdmin致力于提高开发效率&#xff0c;降低开发成本&#xff0c;…...

数字时代PLM系统的重要性

什么是 PLM&#xff08;产品生命周期管理&#xff09;&#xff1f; 从最基本的层面上讲&#xff0c;产品生命周期管理 (PLM)是管理产品从最初构思、开发、服务和处置的整个过程的战略流程。换句话说&#xff0c;PLM 意味着管理产品从诞生到消亡所涉及的一切。 什么是 PLM 软件…...

安卓实现圆形按钮轮廓以及解决无法更改按钮颜色的问题

1.实现按钮轮廓 在drawable文件新建xml文件 <shape xmlns:android"http://schemas.android.com/apk/res/android"<!--实现圆形-->android:shape"oval"><!--指定内部的填充色--><solid android:color"#FFFFFF"/><!-…...

常用原语介绍

1.在Xilinx的example&#xff08;wavegen example&#xff09;中看到他们的顶层模块的输入输出管脚都手动例化原语IBUF以及OBUF——工具也会自动给我们加上不必要自己加 2.非mrcc个srcc的管脚输入的时钟信号&#xff0c;无法进入mmcm和bufg————试验过会报错 3.实际上&…...

29. 透镜阵列

导论&#xff1a; 物理传播光学&#xff08;POP&#xff09;不仅可以用于简单系统&#xff0c;也可以设计优化复杂的光学系统&#xff0c;比如透镜阵列。 设计流程&#xff1a; 透镜阵列建模 在孔径类型中选择“入瞳直径”&#xff0c;并输入2 在视场设定中。设置一个视场&…...

深入理解并打败C语言难关之一————指针(3)

前言&#xff1a; 昨天把指针最为基础的内容讲完了&#xff0c;并且详细说明了传值调用和传址调用的区别&#xff08;这次我也是做到了每日一更&#xff0c;感觉有好多想写的但是没有写完&#xff09;&#xff0c;下面不多废话&#xff0c;下面进入本文想要说的内容 目录&#…...

Ubuntu-24.04-live-server-amd64启用ssh

系列文章目录 Ubuntu-24.04-live-server-amd64安装界面中文版 Ubuntu安装qemu-guest-agent Ubuntu乌班图安装VIM文本编辑器工具 文章目录 系列文章目录前言一、输入安装命令二、使用私钥登录&#xff08;可选&#xff09;1.创建私钥2.生成三个文件说明3.将公钥复制到服务器 三…...

Leetcode 2786. 访问数组中的位置使分数最大(DP 优化)

Leetcode 2786. 访问数组中的位置使分数最大 DP 以每个位置为结尾的序列的分数取决于前方的分数&#xff0c;根据奇偶性计算&#xff0c;取最大值 超时 class Solution {public long maxScore(int[] nums, int x) {int n nums.length;long dp[] new long[n];Arrays.fill(dp…...

【docker实战】使用Dockerfile的COPY拷贝资源遇到的问题

事情是这样的。 在我负责的golang项目中&#xff0c;使用硬代码验证某块逻辑。比如&#xff1a; 于是&#xff0c;为了解决硬代码的问题&#xff0c;我制作了表格工具&#xff1a;【开源项目】Excel数据表自动生成工具v1.0版 – 经云的清净小站 (skycreator.top)。 使用表格工…...

如何用多线程执行 unittest 测试用例实现方案

前言 使用python做过自动化测试的小伙伴&#xff0c;想必都知道unittest和pytest这两个单元测试框架&#xff0c;其中unittest是python的官方库&#xff0c;功能相对于pytest来要逊色不少&#xff0c;但是uniitest使用上手简单&#xff0c;也受到的很多的小伙伴喜爱。一直以来都…...

Ascend310 EP模式下容器内进行推理测试

EP模式下容器内进行推理测试 本文的软硬件环境如下&#xff1a; 机器&#xff1a;x86台式机一台 OS&#xff1a; 5.4.0-26-generic Ubuntu20.04 LTS 推理卡&#xff1a;DLAP200-HP-2&#xff08;凌华基于atlas200模块打造的两模块推理卡&#xff09; 1. 推理卡固件和驱动安…...

(el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程

Ⅰ、Element-plus 提供的Select选择器组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供Select组件情况&#xff1a; 其一、Element-ui 自提供的Select代码情况为(示例的代码)&#xff1a; // Element-plus 提供的组件代码: <template><div class"f…...

Java基础之Math与Array类与System

文章目录 一、Math.random&#xff08;&#xff09;二、Arrays.binarySearch()三、asList&#xff08;&#xff09;四、System tip&#xff1a;以下是正文部分 一、Math.random&#xff08;&#xff09; a < num < b int num (int)(Math.random() * (b - a 1)) a二、…...

【人生底稿 28】新疆出差终章:几番波折终汇报,尽兴踏归津门路

三日游玩尽数落幕&#xff0c;忙碌工作正式回归。轻松的闲暇时光悄然收尾&#xff0c;紧绷的工作状态再次上线。整趟新疆之行&#xff0c;在起伏辗转中迎来最终收尾。一、深夜复盘材料&#xff0c;彻夜待汇报游玩结束回到酒店&#xff0c;我没有松懈休息&#xff0c;静下心重新…...

安全聚合技术:原理、实现与多场景应用

1. 安全聚合技术概述安全聚合&#xff08;Secure Aggregation&#xff09;是一种多方安全计算技术&#xff0c;它允许多个互不信任的参与方在不泄露各自私有数据的前提下&#xff0c;共同计算出一个聚合结果。这项技术的核心价值在于解决了数据隐私与数据共享之间的矛盾&#x…...

在线Graphviz图表编辑器:3步创建专业技术流程图

在线Graphviz图表编辑器&#xff1a;3步创建专业技术流程图 【免费下载链接】GraphvizOnline Lets Graphviz it online 项目地址: https://gitcode.com/gh_mirrors/gr/GraphvizOnline 还在为复杂的技术图表绘制而烦恼吗&#xff1f;GraphvizOnline作为一款革命性的在线G…...

UEFITool深度解析:实战指南与高效使用技巧

UEFITool深度解析&#xff1a;实战指南与高效使用技巧 【免费下载链接】UEFITool UEFI firmware image viewer and editor 项目地址: https://gitcode.com/gh_mirrors/ue/UEFITool UEFITool是一款专为UEFI固件分析设计的开源工具&#xff0c;能够将复杂的二进制固件映像…...

NS-USBLoader:Switch游戏管理终极指南 - 如何实现一键安装与系统引导?

NS-USBLoader&#xff1a;Switch游戏管理终极指南 - 如何实现一键安装与系统引导&#xff1f; 【免费下载链接】ns-usbloader Awoo Installer and GoldLeaf uploader of the NSPs (and other files), RCM payload injector, application for split/merge files. 项目地址: ht…...

基于RAG的智能知识库问答系统:从原理到部署实战

1. 项目概述&#xff1a;当AI大模型遇见知识库&#xff0c;一个开源的智能问答解决方案 最近在折腾一个很有意思的开源项目&#xff0c;叫 zhimaAi/chatwiki 。光看名字&#xff0c;你大概能猜到它的核心&#xff1a; chat 代表对话&#xff0c; wiki 代表知识库。没错&a…...

柔性3D打印与生物仿生设计:从TPU材料到空气喷涂的完整实践

1. 项目概述&#xff1a;当柔性3D打印遇上生物仿生美学如果你和我一样&#xff0c;玩3D打印玩久了&#xff0c;总会对那些千篇一律的硬质塑料件感到一丝审美疲劳。我们总在追求更高的精度、更强的结构&#xff0c;却常常忽略了材料本身可以带来的、截然不同的体验。直到我开始接…...

三维重建下半场,拼的全是底层基建实力!

三维重建已从算法创新竞赛正式迈入基础设施比拼新阶段&#xff0c;主流技术路线逐步收敛&#xff0c;单纯算法红利见顶&#xff0c;行业竞争核心转向数据、算力、平台、生态等底层综合能力。当下竞争不再只比模型效果&#xff0c;而是聚焦四大核心基建维度&#xff1a;采集传感…...

3分钟快速上手:ESP32 Arduino开发环境完整配置指南

3分钟快速上手&#xff1a;ESP32 Arduino开发环境完整配置指南 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 想在熟悉的Arduino环境中开发强大的ESP32物联网项目吗&…...

5分钟学会创建专业交通网络可视化地图

5分钟学会创建专业交通网络可视化地图 【免费下载链接】transit-map The server and client used in transit map simulations like swisstrains.ch 项目地址: https://gitcode.com/gh_mirrors/tr/transit-map 你想在网页上展示动态的公共交通网络吗&#xff1f;Transit…...