当前位置: 首页 > 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二、…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

TCP/IP 网络编程 | 服务端 客户端的封装

设计模式 文章目录 设计模式一、socket.h 接口&#xff08;interface&#xff09;二、socket.cpp 实现&#xff08;implementation&#xff09;三、server.cpp 使用封装&#xff08;main 函数&#xff09;四、client.cpp 使用封装&#xff08;main 函数&#xff09;五、退出方法…...

使用ch340继电器完成随机断电测试

前言 如图所示是市面上常见的OTA压测继电器&#xff0c;通过ch340串口模块完成对继电器的分路控制&#xff0c;这里我编写了一个脚本方便对4路继电器的控制&#xff0c;可以设置开启时间&#xff0c;关闭时间&#xff0c;复位等功能 软件界面 在设备管理器查看串口号后&…...

HTML版英语学习系统

HTML版英语学习系统 这是一个完全免费、无需安装、功能完整的英语学习工具&#xff0c;使用HTML CSS JavaScript实现。 功能 文本朗读练习 - 输入英文文章&#xff0c;系统朗读帮助练习听力和发音&#xff0c;适合跟读练习&#xff0c;模仿学习&#xff1b;实时词典查询 - 双…...

TI德州仪器TPS3103K33DBVR低功耗电压监控器IC电源管理芯片详细解析

1. 基本介绍 TPS3103K33DBVR 是 德州仪器&#xff08;Texas Instruments, TI&#xff09; 推出的一款 低功耗电压监控器&#xff08;Supervisor IC&#xff09;&#xff0c;属于 电源管理芯片&#xff08;PMIC&#xff09; 类别&#xff0c;主要用于 系统复位和电压监测。 2. …...

循环神经网络(RNN):从理论到翻译

循环神经网络&#xff08;RNN&#xff09;是一种专为处理序列数据设计的神经网络&#xff0c;如时间序列、自然语言或语音。与传统的全连接神经网络不同&#xff0c;RNN具有"记忆"功能&#xff0c;通过循环传递信息&#xff0c;使其特别适合需要考虑上下文或顺序的任…...

【版本控制】Git 和 GitHub 入门教程

目录 0 引言1 Git与GitHub的诞生1.1 Git&#xff1a;Linus的“两周奇迹”&#xff0c;拯救Linux内核1.2 GitHub&#xff1a;为Git插上协作的翅膀1.3 协同进化&#xff1a;从工具到生态的质变1.4 关键历程时间轴&#xff08;2005–2008&#xff09; 2 Git与GitHub入门指南2.1 Gi…...

Life:Internship finding

1. 前言 fishwheel writes this Blog to 记录自分自身在研二下找实习的经历。When 写这篇 Blog 的时候我的最后一搏也挂掉了&#xff0c;只能启用保底方案了。When I 打开我的邮箱时&#xff0c;发现里面有 nearly 100 多封与之相关的邮件&#xff0c;顿时感到有些心凉&#x…...