翼度科技»论坛 编程开发 .net 查看内容

C#控件ListView支持添加TextBox\PictureBox等其他控件

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
功能说明

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

实现方法

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

  • ListView需要设置OwnerDraw=true,并重载自绘函数OnDrawColumnHeader、OnDrawItem、OnDrawSubItem
  • 支持按单元格添加对应的控件,其Parent设置为列表ListView
  • 列表界面调整后,包括大小、列表头、滚动等,需重新绘制单元格的控件
实现源码
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows.Forms;
  8. namespace MyListView.Ui
  9. {
  10.     #region ListViewEx
  11.     public class ListViewEx : ListView
  12.     {
  13.         #region 内部属性
  14.         /// <summary>
  15.         /// 存放单元格控件
  16.         /// </summary>
  17.         List<Control> _CellControls = new List<Control>();
  18.         /// <summary>
  19.         /// 界面是否发生变化
  20.         /// </summary>
  21.         bool IsViewChanged { get; set; }
  22.         #endregion
  23.         #region 方法
  24.         /// <summary>
  25.         /// 构造函数
  26.         /// </summary>
  27.         public ListViewEx()
  28.         {
  29.             #region 初始化
  30.             #endregion
  31.             #region 事件
  32.             this.ColumnReordered += ColumnWidthChangedHandler;
  33.             this.ColumnWidthChanged += ColumnWidthChangedHandler;
  34.             #endregion
  35.         }
  36.         /// <summary>
  37.         /// 添加控件
  38.         /// </summary>
  39.         /// <typeparam name="T"></typeparam>
  40.         /// <param name="row"></param>
  41.         /// <param name="col"></param>
  42.         /// <param name="c"></param>
  43.         /// <returns></returns>
  44.         public T Add<T>(int row, int col, T c) where T : Control
  45.         {
  46.             if(row >= this.Items.Count || col >= this.Columns.Count)
  47.             {
  48.                 return null;
  49.             }
  50.             var index = (row * this.Columns.Count) + col;
  51.             for (var i = _CellControls.Count; i <= index; i++)
  52.             {
  53.                 _CellControls.Add(null);
  54.             }
  55.             var oc = _CellControls[index];
  56.             if (oc != null)
  57.             {
  58.                 oc.Dispose();
  59.             }
  60.             OwnerDraw = true;
  61.             IsViewChanged = true;
  62.             c.Parent = this;
  63.             _CellControls[index] = c;
  64.             return c;
  65.         }
  66.         /// <summary>
  67.         /// 设置行高度
  68.         /// </summary>
  69.         /// <param name="height"></param>
  70.         public void SetItemHeight(int height)
  71.         {
  72.             if(this.SmallImageList == null)
  73.             {
  74.                 this.SmallImageList = new ImageList();
  75.             }
  76.             this.SmallImageList.ImageSize = new Size(1, height);
  77.         }
  78.         #endregion
  79.         #region 内部函数
  80.         void ColumnWidthChangedHandler(object s, EventArgs e)
  81.         {
  82.             IsViewChanged = true;
  83.         }
  84.         /// <summary>
  85.         /// 显示控件到目标单元格
  86.         /// </summary>
  87.         /// <param name="c"></param>
  88.         /// <param name="item"></param>
  89.         void ShowCellControl(Control c, ListViewItem.ListViewSubItem item)
  90.         {
  91.             int margin = 2;
  92.             c.Text = item.Text;
  93.             c.Visible = true;
  94.             c.Bounds = new Rectangle(item.Bounds.X + margin,
  95.                 item.Bounds.Top + margin,
  96.                 item.Bounds.Width - 2 * margin,
  97.                 item.Bounds.Height - 2 * margin);
  98.         }
  99.         /// <summary>
  100.         /// 显示单元格控件
  101.         /// </summary>
  102.         /// <param name="e"></param>
  103.         /// <returns></returns>
  104.         Control GetCellControl(DrawListViewSubItemEventArgs e)
  105.         {
  106.             Control c = null;
  107.             #region 获取控件
  108.             var index = (e.ItemIndex * this.Columns.Count) + e.ColumnIndex;
  109.             if (index >= _CellControls.Count)
  110.             {
  111.                 return null;
  112.             }
  113.             c = _CellControls[index];
  114.             #endregion
  115.             return c;
  116.         }
  117.         protected override void WndProc(ref Message m)
  118.         {
  119.             #region 事件定义
  120.             const int WM_SIZE = 0x0005;
  121.             const int WM_PAINT = 0x000F;
  122.             const int WM_HSCROLL = 0x114;
  123.             const int WM_VSCROLL = 0x115;
  124.             const int WM_MOUSEWHEEL = 0x020A;
  125.             #endregion
  126.             #region 重绘显示控件
  127.             if (m.Msg == WM_PAINT && IsViewChanged)
  128.             {
  129.                 if(this.Columns.Count > 0)
  130.                 {
  131.                     for (var i = 0; i < _CellControls.Count; i++)
  132.                     {
  133.                         var cell_control = _CellControls[i];
  134.                         if (cell_control == null)
  135.                         {
  136.                             continue;
  137.                         }
  138.                         cell_control.Visible = false;
  139.                         var row = i / this.Columns.Count;
  140.                         var col = i % this.Columns.Count;
  141.                         if(row >= Items.Count || col >= this.Columns.Count)
  142.                         {
  143.                             continue;
  144.                         }
  145.                         var item = this.Items[row];
  146.                         if(item.Bounds.Y < 0 || item.Bounds.Y >= this.Height)
  147.                         {
  148.                             continue;
  149.                         }
  150.                         if(item.SubItems[col].Bounds.X < 0 || item.SubItems[col].Bounds.X >= this.Width)
  151.                         {
  152.                             continue;
  153.                         }
  154.                         ShowCellControl(cell_control, item.SubItems[col]);
  155.                     }
  156.                     IsViewChanged = false;
  157.                 }
  158.             }
  159.             else if(m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_SIZE)
  160.             {
  161.                 IsViewChanged = true;
  162.             }
  163.             #endregion
  164.             base.WndProc(ref m);
  165.         }
  166.         protected override void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
  167.         {
  168.             e.DrawDefault = true;
  169.         }
  170.         protected override void OnDrawItem(DrawListViewItemEventArgs e)
  171.         {
  172.             // 已经在OnDrawSubItem处理过了
  173.             // e.DrawText(TextFormatFlags.Default);
  174.         }
  175.         protected override void OnDrawSubItem(DrawListViewSubItemEventArgs e)
  176.         {
  177.             if(GetCellControl(e) != null)
  178.             {
  179.                 return;
  180.             }
  181.             else
  182.             {
  183.                 e.DrawDefault = true;
  184.             }
  185.         }
  186.         #endregion
  187.     }
  188.     #endregion
  189. }
复制代码
测试代码

[code]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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具