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

烂漫一生 提交于 2019-11-28 05:12:31

前提

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

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

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

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

欢迎前来交流探讨: 企鹅群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 点个星星吧

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!