• (四十三)c#Winform自定义控件-Listview-HZHControls


    官网

    http://www.hzhcontrols.com

    前提

    入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

    GitHub:https://github.com/kwwwvagaa/NetWinformControl

    码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

    如果觉得写的还行,请点个 star 支持一下吧

    欢迎前来交流探讨: 企鹅群568015492 企鹅群568015492

    麻烦博客下方点个【推荐】,谢谢

    NuGet

    Install-Package HZH_Controls

    目录

    https://www.cnblogs.com/bfyx/p/11364884.html

    用处及效果

    使用分页控件效果

    不使用分页控件效果

    准备工作

    我们需要元素控件,需要列表控件,另外为了具有更好的扩展性,元素控件实现接口,方便进行扩展

    我们用到了分页控件,如果你还不了解,请移步查看

    (十二)c#Winform自定义控件-分页控件

    我们这里的元素控件用到圆角,故继承基类控件UCControlBase,如果不了解,请移步查看

    (一)c#Winform自定义控件-基类控件

    开始

    添加一个接口,用来约束元素控件

     1  public interface IListViewItem
     2     {
     3         /// <summary>
     4         /// 数据源
     5         /// </summary>
     6         object DataSource { get; set; }
     7         /// <summary>
     8         /// 选中项事件
     9         /// </summary>
    10         event EventHandler SelectedItemEvent;
    11         /// <summary>
    12         /// 选中处理,一般用以更改选中效果
    13         /// </summary>
    14         /// <param name="blnSelected">是否选中</param>
    15         void SetSelected(bool blnSelected);
    16     }

    添加一个元素控件,命名UCListViewItem,我们这里继承基类控件UCControlBase,实现接口IListViewItem

     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Drawing;
     5 using System.Data;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Windows.Forms;
     9 
    10 namespace HZH_Controls.Controls
    11 {
    12     [ToolboxItem(false)]
    13     public partial class UCListViewItem : UCControlBase, IListViewItem
    14     {
    15         private object m_dataSource;
    16         public object DataSource
    17         {
    18             get
    19             {
    20                 return m_dataSource;
    21             }
    22             set
    23             {
    24                 m_dataSource = value;
    25                 lblTitle.Text = value.ToString();
    26             }
    27         }
    28 
    29         public event EventHandler SelectedItemEvent;
    30         public UCListViewItem()
    31         {
    32             InitializeComponent();
    33             lblTitle.MouseDown += lblTitle_MouseDown;
    34         }
    35 
    36         void lblTitle_MouseDown(object sender, MouseEventArgs e)
    37         {
    38             if (SelectedItemEvent != null)
    39             {
    40                 SelectedItemEvent(this, e);
    41             }
    42         }
    43 
    44         public void SetSelected(bool blnSelected)
    45         {
    46             if (blnSelected)
    47                 this.FillColor = Color.FromArgb(255, 247, 245);
    48             else
    49                 this.FillColor = Color.White;
    50             this.Refresh();
    51         }
    52     }
    53 }
     1 namespace HZH_Controls.Controls
     2 {
     3     partial class UCListViewItem
     4     {
     5         /// <summary> 
     6         /// 必需的设计器变量。
     7         /// </summary>
     8         private System.ComponentModel.IContainer components = null;
     9 
    10         /// <summary> 
    11         /// 清理所有正在使用的资源。
    12         /// </summary>
    13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    14         protected override void Dispose(bool disposing)
    15         {
    16             if (disposing && (components != null))
    17             {
    18                 components.Dispose();
    19             }
    20             base.Dispose(disposing);
    21         }
    22 
    23         #region 组件设计器生成的代码
    24 
    25         /// <summary> 
    26         /// 设计器支持所需的方法 - 不要
    27         /// 使用代码编辑器修改此方法的内容。
    28         /// </summary>
    29         private void InitializeComponent()
    30         {
    31             this.lblTitle = new System.Windows.Forms.Label();
    32             this.SuspendLayout();
    33             // 
    34             // lblTitle
    35             // 
    36             this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
    37             this.lblTitle.Location = new System.Drawing.Point(0, 0);
    38             this.lblTitle.Name = "lblTitle";
    39             this.lblTitle.Size = new System.Drawing.Size(107, 96);
    40             this.lblTitle.TabIndex = 0;
    41             this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
    42             // 
    43             // UCListViewItem
    44             // 
    45             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    46             this.BackColor = System.Drawing.Color.Transparent;
    47             this.Controls.Add(this.lblTitle);
    48             this.FillColor = System.Drawing.Color.White;
    49             this.IsRadius = true;
    50             this.IsShowRect = true;
    51             this.Name = "UCListViewItem";
    52             this.RectColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(232)))), ((int)(((byte)(232)))));
    53             this.Size = new System.Drawing.Size(107, 96);
    54             this.ResumeLayout(false);
    55 
    56         }
    57 
    58         #endregion
    59 
    60         private System.Windows.Forms.Label lblTitle;
    61     }
    62 }
    View Code

    然后需要一个列表来显示元素控件

    添加一个用户控件,命名UCListView

    一些属性

      1 int m_intCellWidth = 130;//单元格宽度
      2         int m_intCellHeight = 120;//单元格高度
      3 
      4         private Type m_itemType = typeof(UCListViewItem);
      5 
      6         [Description("单元格类型,如果无法满足您的需求,你可以自定义单元格控件,并实现接口IListViewItem"), Category("自定义")]
      7         public Type ItemType
      8         {
      9             get { return m_itemType; }
     10             set
     11             {
     12                 if (!typeof(IListViewItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
     13                     throw new Exception("单元格控件没有继承实现接口IListViewItem");
     14                 m_itemType = value;
     15             }
     16         }
     17 
     18         private UCPagerControlBase m_page = null;
     19         /// <summary>
     20         /// 翻页控件
     21         /// </summary>
     22         [Description("翻页控件,如果UCPagerControl不满足你的需求,请自定义翻页控件并继承UCPagerControlBase"), Category("自定义")]
     23         public UCPagerControlBase Page
     24         {
     25             get { return m_page; }
     26             set
     27             {
     28                 m_page = value;
     29                 if (value != null)
     30                 {
     31                     if (!typeof(IPageControl).IsAssignableFrom(value.GetType()) || !value.GetType().IsSubclassOf(typeof(UCPagerControlBase)))
     32                         throw new Exception("翻页控件没有继承UCPagerControlBase");
     33                     this.panMain.AutoScroll = false;
     34                     panPage.Visible = true;
     35                     this.Controls.SetChildIndex(panMain, 0);
     36                     m_page.ShowSourceChanged += m_page_ShowSourceChanged;
     37                     m_page.Dock = DockStyle.Fill;
     38                     this.panPage.Controls.Clear();
     39                     this.panPage.Controls.Add(m_page);
     40                     GetCellCount();
     41                     this.DataSource = m_page.GetCurrentSource();
     42                 }
     43                 else
     44                 {
     45                     this.panMain.AutoScroll = true;
     46                     m_page = null;
     47                     panPage.Visible = false;
     48                 }
     49             }
     50         }
     51 
     52 
     53 
     54         private object m_dataSource = null;
     55 
     56         [Description("数据源,如果使用翻页控件,请使用翻页控件的DataSource"), Category("自定义")]
     57         public object DataSource
     58         {
     59             get { return m_dataSource; }
     60             set
     61             {
     62                 if (value == null)
     63                     return;
     64                 if (!typeof(IList).IsAssignableFrom(value.GetType()))
     65                 {
     66                     throw new Exception("数据源不是有效的数据类型,列表");
     67                 }
     68                 m_dataSource = value;
     69                 ReloadSource();
     70             }
     71         }
     72 
     73         int m_intCellCount = 0;//单元格总数
     74         [Description("单元格总数"), Category("自定义")]
     75         public int CellCount
     76         {
     77             get { return m_intCellCount; }
     78             private set
     79             {
     80                 m_intCellCount = value;
     81                 if (value > 0 && m_page != null)
     82                 {
     83                     m_page.PageSize = m_intCellCount;
     84                     m_page.Reload();
     85                 }
     86             }
     87         }
     88 
     89         private List<object> m_selectedSource = new List<object>();
     90 
     91         [Description("选中的数据"), Category("自定义")]
     92         public List<object> SelectedSource
     93         {
     94             get { return m_selectedSource; }
     95             set
     96             {
     97                 m_selectedSource = value;
     98                 ReloadSource();
     99             }
    100         }
    101 
    102         private bool m_isMultiple = true;
    103 
    104         [Description("是否多选"), Category("自定义")]
    105         public bool IsMultiple
    106         {
    107             get { return m_isMultiple; }
    108             set { m_isMultiple = value; }
    109         }
    110 
    111         [Description("选中项事件"), Category("自定义")]
    112         public event EventHandler SelectedItemEvent;
    113         public delegate void ReloadGridStyleEventHandle(int intCellCount);
    114         /// <summary>
    115         /// 样式改变事件
    116         /// </summary>
    117         [Description("样式改变事件"), Category("自定义")]
    118         public event ReloadGridStyleEventHandle ReloadGridStyleEvent;

    一下辅助函数

      1 #region 重新加载数据源
      2         /// <summary>
      3         /// 功能描述:重新加载数据源
      4         /// 作  者:HZH
      5         /// 创建日期:2019-06-27 16:47:32
      6         /// 任务编号:POS
      7         /// </summary>
      8         public void ReloadSource()
      9         {
     10             ControlHelper.FreezeControl(this, true);
     11             if (this.panMain.Controls.Count <= 0)
     12             {
     13                 ReloadGridStyle();
     14             }
     15             if (m_dataSource == null || ((IList)m_dataSource).Count <= 0)
     16             {
     17                 for (int i = this.panMain.Controls.Count - 1; i >= 0; i--)
     18                 {
     19                     this.panMain.Controls[i].Visible = false;
     20                 }
     21 
     22                 return;
     23             }
     24             int intCount = Math.Min(((IList)m_dataSource).Count, this.panMain.Controls.Count);
     25 
     26             for (int i = 0; i < intCount; i++)
     27             {
     28                 ((IListViewItem)this.panMain.Controls[i]).DataSource = ((IList)m_dataSource)[i];
     29                 if (m_selectedSource.Contains(((IList)m_dataSource)[i]))
     30                 {
     31                     ((IListViewItem)this.panMain.Controls[i]).SetSelected(true);
     32                 }
     33                 else
     34                 {
     35                     ((IListViewItem)this.panMain.Controls[i]).SetSelected(false);
     36                 }
     37                 this.panMain.Controls[i].Visible = true;
     38             }
     39 
     40             for (int i = this.panMain.Controls.Count - 1; i >= intCount; i--)
     41             {
     42                 if (this.panMain.Controls[i].Visible)
     43                     this.panMain.Controls[i].Visible = false;
     44             }
     45             ControlHelper.FreezeControl(this, false);
     46         }
     47         #endregion
     48 
     49         #region 刷新表格
     50         /// <summary>
     51         /// 功能描述:刷新表格样式
     52         /// 作  者:HZH
     53         /// 创建日期:2019-06-27 16:35:25
     54         /// 任务编号:POS
     55         /// </summary>
     56         public void ReloadGridStyle()
     57         {
     58             Form frmMain = this.FindForm();
     59             if (frmMain != null && !frmMain.IsDisposed && frmMain.Visible && this.Visible)
     60             {
     61                 GetCellCount();
     62                 try
     63                 {
     64                     ControlHelper.FreezeControl(this, true);
     65                     if (this.panMain.Controls.Count < m_intCellCount)
     66                     {
     67                         int intControlsCount = this.panMain.Controls.Count;
     68                         for (int i = 0; i < m_intCellCount - intControlsCount; i++)
     69                         {
     70                             Control uc = (Control)Activator.CreateInstance(m_itemType);
     71                             uc.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5);
     72 
     73                             (uc as IListViewItem).SelectedItemEvent += UCListView_SelectedItemEvent;
     74                             uc.Visible = false;
     75                             this.panMain.Controls.Add(uc);
     76                         }
     77                     }
     78                     else if (this.panMain.Controls.Count > m_intCellCount)
     79                     {
     80                         int intControlsCount = this.panMain.Controls.Count;
     81                         for (int i = intControlsCount - 1; i > m_intCellCount - 1; i--)
     82                         {
     83                             this.panMain.Controls.RemoveAt(i);
     84                         }
     85                     }
     86                     foreach (Control item in this.panMain.Controls)
     87                     {
     88                         item.Size = new Size(m_intCellWidth, m_intCellHeight);
     89                     }
     90                 }
     91                 finally
     92                 {
     93                     ControlHelper.FreezeControl(this, false);
     94                 }
     95                 if (ReloadGridStyleEvent != null)
     96                 {
     97                     ReloadGridStyleEvent(m_intCellCount);
     98                 }
     99             }
    100 
    101         }
    102 
    103         void UCListView_SelectedItemEvent(object sender, EventArgs e)
    104         {
    105             var selectedItem = sender as IListViewItem;
    106 
    107             if (m_selectedSource.Contains(selectedItem.DataSource))
    108             {
    109                 m_selectedSource.Remove(selectedItem.DataSource);
    110                 selectedItem.SetSelected(false);
    111             }
    112             else
    113             {
    114                 if (m_isMultiple)
    115                 {
    116                     m_selectedSource.Add(selectedItem.DataSource);
    117                     selectedItem.SetSelected(true);
    118                 }
    119                 else
    120                 {
    121                     if (m_selectedSource.Count > 0)
    122                     {
    123                         int intCount = Math.Min(((IList)m_dataSource).Count, this.panMain.Controls.Count);
    124                         for (int i = 0; i < intCount; i++)
    125                         {
    126                             var item = ((IListViewItem)this.panMain.Controls[i]);
    127                             if (m_selectedSource.Contains(item.DataSource))
    128                             {
    129                                 item.SetSelected(false);
    130                                 break;
    131                             }
    132                         }
    133                     }
    134 
    135                     m_selectedSource = new List<object>() { selectedItem.DataSource };
    136                     selectedItem.SetSelected(true);
    137 
    138                 }
    139             }
    140 
    141             if (SelectedItemEvent != null)
    142             {
    143                 SelectedItemEvent(sender, e);
    144             }
    145         }
    146         #endregion
    147 
    148         #region 获取cell总数
    149         /// <summary>
    150         /// 功能描述:获取cell总数
    151         /// 作  者:HZH
    152         /// 创建日期:2019-06-27 16:28:58
    153         /// 任务编号:POS
    154         /// </summary>
    155         private void GetCellCount()
    156         {
    157             if (this.panMain.Width == 0)
    158                 return;
    159             Control item = (Control)Activator.CreateInstance(m_itemType);
    160 
    161 
    162             int intXCount = (this.panMain.Width - 10) / (item.Width + 10);
    163             m_intCellWidth = item.Width + ((this.panMain.Width - 10) % (item.Width + 10)) / intXCount;
    164 
    165             int intYCount = (this.panMain.Height - 10) / (item.Height + 10);
    166             m_intCellHeight = item.Height + ((this.panMain.Height - 10) % (item.Height + 10)) / intYCount;
    167             int intCount = intXCount * intYCount;
    168 
    169             if (Page == null)
    170             {
    171                 if (((IList)m_dataSource).Count > intCount)
    172                 {
    173                     intXCount = (this.panMain.Width - 10 - 20) / (item.Width + 10);
    174                     m_intCellWidth = item.Width + ((this.panMain.Width - 10 - 20) % (item.Width + 10)) / intXCount;
    175                 }
    176                 intCount = Math.Max(intCount, ((IList)m_dataSource).Count);
    177             }
    178 
    179             CellCount = intCount;
    180         }
    181         #endregion

    一些事件

        private void panMain_Resize(object sender, EventArgs e)
            {
                ReloadGridStyle();
            }
    void m_page_ShowSourceChanged(object currentSource)
            {
                this.DataSource = currentSource;
            }

    你会发现,有个ItemType属性,这个用来定义列表呈现那种子元素,这么用的好处就是,当你觉得我写的这个元素控件UCListViewItem并不能满足你需求的时候,你可以添加一个自定义控件,并实现接口IListViewItem,然后将你自定义的控件指定给这个属性,列表就会呈现出来了,是不是很方便,列表会自动根据你的元素控件的大小来适量调整来填充到列表中的。

    还有一个Page属性,这个是用来表示用哪个分页控件,当然你也可以不用,我已经提供了2种分页控件,如果你觉得还是不满足你的话,去参考分页控件那个文章,自己添加一个分页控件吧。

    最后的话

    如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧

  • 相关阅读:
    SecondiosAppTutorial--学习笔记
    Your First iOS App--苹果官方iOS文档学习
    使用cocoapods碰到的难题
    xcode6 使用pch出错解决办法
    Mac上安装与更新Ruby,Rails运行环境
    对contentoffset的理解
    CALayer笔记
    StoryBoard解惑
    post和get请求
    程序内部让用户直接上appstore评价游戏的链接地址以及跳转方法
  • 原文地址:https://www.cnblogs.com/bfyx/p/11393405.html
Copyright © 2020-2023  润新知