(四十三)c#Winform自定义控件-Listview-HZHControls
官网
前提
入行已经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
用处及效果
使用分页控件效果

不使用分页控件效果

准备工作
我们需要元素控件,需要列表控件,另外为了具有更好的扩展性,元素控件实现接口,方便进行扩展
我们用到了分页控件,如果你还不了解,请移步查看
我们这里的元素控件用到圆角,故继承基类控件UCControlBase,如果不了解,请移步查看
开始
添加一个接口,用来约束元素控件
public interface IListViewItem
{
/// <summary>
/// 数据源
/// </summary>
object DataSource { get; set; }
/// <summary>
/// 选中项事件
/// </summary>
event EventHandler SelectedItemEvent;
/// <summary>
/// 选中处理,一般用以更改选中效果
/// </summary>
/// <param name="blnSelected">是否选中</param>
void SetSelected(bool blnSelected);
}
添加一个元素控件,命名UCListViewItem,我们这里继承基类控件UCControlBase,实现接口IListViewItem
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms; namespace HZH_Controls.Controls
{
[ToolboxItem(false)]
public partial class UCListViewItem : UCControlBase, IListViewItem
{
private object m_dataSource;
public object DataSource
{
get
{
return m_dataSource;
}
set
{
m_dataSource = value;
lblTitle.Text = value.ToString();
}
} public event EventHandler SelectedItemEvent;
public UCListViewItem()
{
InitializeComponent();
lblTitle.MouseDown += lblTitle_MouseDown;
} void lblTitle_MouseDown(object sender, MouseEventArgs e)
{
if (SelectedItemEvent != null)
{
SelectedItemEvent(this, e);
}
} public void SetSelected(bool blnSelected)
{
if (blnSelected)
this.FillColor = Color.FromArgb(, , );
else
this.FillColor = Color.White;
this.Refresh();
}
}
}
namespace HZH_Controls.Controls
{
partial class UCListViewItem
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null; /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
} #region 组件设计器生成的代码 /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.lblTitle = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lblTitle
//
this.lblTitle.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblTitle.Location = new System.Drawing.Point(, );
this.lblTitle.Name = "lblTitle";
this.lblTitle.Size = new System.Drawing.Size(, );
this.lblTitle.TabIndex = ;
this.lblTitle.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// UCListViewItem
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.Transparent;
this.Controls.Add(this.lblTitle);
this.FillColor = System.Drawing.Color.White;
this.IsRadius = true;
this.IsShowRect = true;
this.Name = "UCListViewItem";
this.RectColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
this.Size = new System.Drawing.Size(, );
this.ResumeLayout(false); } #endregion private System.Windows.Forms.Label lblTitle;
}
}
然后需要一个列表来显示元素控件
添加一个用户控件,命名UCListView
一些属性
int m_intCellWidth = ;//单元格宽度
int m_intCellHeight = ;//单元格高度 private Type m_itemType = typeof(UCListViewItem); [Description("单元格类型,如果无法满足您的需求,你可以自定义单元格控件,并实现接口IListViewItem"), Category("自定义")]
public Type ItemType
{
get { return m_itemType; }
set
{
if (!typeof(IListViewItem).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
throw new Exception("单元格控件没有继承实现接口IListViewItem");
m_itemType = value;
}
} private UCPagerControlBase m_page = null;
/// <summary>
/// 翻页控件
/// </summary>
[Description("翻页控件,如果UCPagerControl不满足你的需求,请自定义翻页控件并继承UCPagerControlBase"), Category("自定义")]
public UCPagerControlBase Page
{
get { return m_page; }
set
{
m_page = value;
if (value != null)
{
if (!typeof(IPageControl).IsAssignableFrom(value.GetType()) || !value.GetType().IsSubclassOf(typeof(UCPagerControlBase)))
throw new Exception("翻页控件没有继承UCPagerControlBase");
this.panMain.AutoScroll = false;
panPage.Visible = true;
this.Controls.SetChildIndex(panMain, );
m_page.ShowSourceChanged += m_page_ShowSourceChanged;
m_page.Dock = DockStyle.Fill;
this.panPage.Controls.Clear();
this.panPage.Controls.Add(m_page);
GetCellCount();
this.DataSource = m_page.GetCurrentSource();
}
else
{
this.panMain.AutoScroll = true;
m_page = null;
panPage.Visible = false;
}
}
} private object m_dataSource = null; [Description("数据源,如果使用翻页控件,请使用翻页控件的DataSource"), Category("自定义")]
public object DataSource
{
get { return m_dataSource; }
set
{
if (value == null)
return;
if (!typeof(IList).IsAssignableFrom(value.GetType()))
{
throw new Exception("数据源不是有效的数据类型,列表");
}
m_dataSource = value;
ReloadSource();
}
} int m_intCellCount = ;//单元格总数
[Description("单元格总数"), Category("自定义")]
public int CellCount
{
get { return m_intCellCount; }
private set
{
m_intCellCount = value;
if (value > && m_page != null)
{
m_page.PageSize = m_intCellCount;
m_page.Reload();
}
}
} private List<object> m_selectedSource = new List<object>(); [Description("选中的数据"), Category("自定义")]
public List<object> SelectedSource
{
get { return m_selectedSource; }
set
{
m_selectedSource = value;
ReloadSource();
}
} private bool m_isMultiple = true; [Description("是否多选"), Category("自定义")]
public bool IsMultiple
{
get { return m_isMultiple; }
set { m_isMultiple = value; }
} [Description("选中项事件"), Category("自定义")]
public event EventHandler SelectedItemEvent;
public delegate void ReloadGridStyleEventHandle(int intCellCount);
/// <summary>
/// 样式改变事件
/// </summary>
[Description("样式改变事件"), Category("自定义")]
public event ReloadGridStyleEventHandle ReloadGridStyleEvent;
一下辅助函数
#region 重新加载数据源
/// <summary>
/// 功能描述:重新加载数据源
/// 作 者:HZH
/// 创建日期:2019-06-27 16:47:32
/// 任务编号:POS
/// </summary>
public void ReloadSource()
{
ControlHelper.FreezeControl(this, true);
if (this.panMain.Controls.Count <= )
{
ReloadGridStyle();
}
if (m_dataSource == null || ((IList)m_dataSource).Count <= )
{
for (int i = this.panMain.Controls.Count - ; i >= ; i--)
{
this.panMain.Controls[i].Visible = false;
} return;
}
int intCount = Math.Min(((IList)m_dataSource).Count, this.panMain.Controls.Count); for (int i = ; i < intCount; i++)
{
((IListViewItem)this.panMain.Controls[i]).DataSource = ((IList)m_dataSource)[i];
if (m_selectedSource.Contains(((IList)m_dataSource)[i]))
{
((IListViewItem)this.panMain.Controls[i]).SetSelected(true);
}
else
{
((IListViewItem)this.panMain.Controls[i]).SetSelected(false);
}
this.panMain.Controls[i].Visible = true;
} for (int i = this.panMain.Controls.Count - ; i >= intCount; i--)
{
if (this.panMain.Controls[i].Visible)
this.panMain.Controls[i].Visible = false;
}
ControlHelper.FreezeControl(this, false);
}
#endregion #region 刷新表格
/// <summary>
/// 功能描述:刷新表格样式
/// 作 者:HZH
/// 创建日期:2019-06-27 16:35:25
/// 任务编号:POS
/// </summary>
public void ReloadGridStyle()
{
Form frmMain = this.FindForm();
if (frmMain != null && !frmMain.IsDisposed && frmMain.Visible && this.Visible)
{
GetCellCount();
try
{
ControlHelper.FreezeControl(this, true);
if (this.panMain.Controls.Count < m_intCellCount)
{
int intControlsCount = this.panMain.Controls.Count;
for (int i = ; i < m_intCellCount - intControlsCount; i++)
{
Control uc = (Control)Activator.CreateInstance(m_itemType);
uc.Margin = new System.Windows.Forms.Padding(, , , ); (uc as IListViewItem).SelectedItemEvent += UCListView_SelectedItemEvent;
uc.Visible = false;
this.panMain.Controls.Add(uc);
}
}
else if (this.panMain.Controls.Count > m_intCellCount)
{
int intControlsCount = this.panMain.Controls.Count;
for (int i = intControlsCount - ; i > m_intCellCount - ; i--)
{
this.panMain.Controls.RemoveAt(i);
}
}
foreach (Control item in this.panMain.Controls)
{
item.Size = new Size(m_intCellWidth, m_intCellHeight);
}
}
finally
{
ControlHelper.FreezeControl(this, false);
}
if (ReloadGridStyleEvent != null)
{
ReloadGridStyleEvent(m_intCellCount);
}
} } void UCListView_SelectedItemEvent(object sender, EventArgs e)
{
var selectedItem = sender as IListViewItem; if (m_selectedSource.Contains(selectedItem.DataSource))
{
m_selectedSource.Remove(selectedItem.DataSource);
selectedItem.SetSelected(false);
}
else
{
if (m_isMultiple)
{
m_selectedSource.Add(selectedItem.DataSource);
selectedItem.SetSelected(true);
}
else
{
if (m_selectedSource.Count > )
{
int intCount = Math.Min(((IList)m_dataSource).Count, this.panMain.Controls.Count);
for (int i = ; i < intCount; i++)
{
var item = ((IListViewItem)this.panMain.Controls[i]);
if (m_selectedSource.Contains(item.DataSource))
{
item.SetSelected(false);
break;
}
}
} m_selectedSource = new List<object>() { selectedItem.DataSource };
selectedItem.SetSelected(true); }
} if (SelectedItemEvent != null)
{
SelectedItemEvent(sender, e);
}
}
#endregion #region 获取cell总数
/// <summary>
/// 功能描述:获取cell总数
/// 作 者:HZH
/// 创建日期:2019-06-27 16:28:58
/// 任务编号:POS
/// </summary>
private void GetCellCount()
{
if (this.panMain.Width == )
return;
Control item = (Control)Activator.CreateInstance(m_itemType); int intXCount = (this.panMain.Width - ) / (item.Width + );
m_intCellWidth = item.Width + ((this.panMain.Width - ) % (item.Width + )) / intXCount; int intYCount = (this.panMain.Height - ) / (item.Height + );
m_intCellHeight = item.Height + ((this.panMain.Height - ) % (item.Height + )) / intYCount;
int intCount = intXCount * intYCount; if (Page == null)
{
if (((IList)m_dataSource).Count > intCount)
{
intXCount = (this.panMain.Width - - ) / (item.Width + );
m_intCellWidth = item.Width + ((this.panMain.Width - - ) % (item.Width + )) / intXCount;
}
intCount = Math.Max(intCount, ((IList)m_dataSource).Count);
} CellCount = intCount;
}
#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 点个星星吧
(四十三)c#Winform自定义控件-Listview-HZHControls的更多相关文章
- (四十四)c#Winform自定义控件-水波-HZHControls
官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...
- (四)c#Winform自定义控件-选择按钮组
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- (二十四)c#Winform自定义控件-单标题窗体
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- (四十)c#Winform自定义控件-开关-HZHControls
官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...
- (十四)c#Winform自定义控件-键盘(一)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- (五十四)c#Winform自定义控件-仪表盘
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- (六十四)c#Winform自定义控件-温度计(工业)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- (七十四)c#Winform自定义控件-金字塔图表
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- (八十四)c#Winform自定义控件-导航菜单(类Office菜单)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- (四十六)c#Winform自定义控件-水波进度条-HZHControls
官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...
随机推荐
- C语言笔记 08_函数指针&回调函数&字符串&结构体&位域
函数指针 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调用函数.传递参数. 函数指针变量的声明: / ...
- 小白的springboot之路(十一)、构建后台RESTfull API
0.前言 开发系统中,前后端分离,后端一般返回RESTfull API,前端调用API构建UI,彼此分离.互相完全独立: 后台API中,我们一般返回结果码.提示信息.数据三部分内容,如图: 我们今天 ...
- NLP标注工具brat 配置文件说明
快速搭建brat 通过docker: docker run --name=brat -d -p 38080:80 -e BRAT_USERNAME=brat -e BRAT_PASSWORD=brat ...
- AOP框架Dora.Interception 3.0 [5]: 基于策略的拦截器注册方式
注册拦截器旨在解决如何将拦截器应用到目标方法的问题.在我看来,针对拦截器的注册应该是明确而精准的,也就是我们提供的注册方式应该让拦截器准确地应用到期望的目标方法上,不能多也不能少.如果注册的方式过于模 ...
- 动态代理模式_应用(Redis工具类)
本次使用动态代理的初衷是学习Redis,使用Java操作Redis时用到Jedis的JedisPool,而后对Jedis的方法进一步封装完善成为一个工具类.因为直接使用Jedis对象时,为了保证性能, ...
- Linux_crontab参数表示的意思
* * * * * (下面的字体对应) 分 时 日 月 周 星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满 ...
- 代码管理平台之git
yum install -y gitmkdir -p /date/gitrootcd !$git init git add 1.txtgit commit -m "add 1.txt&quo ...
- Java之缓冲流(字节/字符缓冲流)
概述 缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类: 字节缓冲流: BufferedInputStream , BufferedOutputStrea ...
- IEEE754 32位浮点数表示范围
6.1浮点数的数值范围 根据上面的探讨,浮点数可以表示-∞到+∞,这只是一种特殊情况,显然不是我们想要的数值范围. 以32位单精度浮点数为例,阶码E由8位表示,取值范围为0-255,去除0和255这两 ...
- jimdb压测踩坑记
本文记录在jimdb压测过程中遇到的各种小坑,望能够抛砖引玉. 1.压测流量起来后,过了5分钟左右,发现ops突降,大概降了三分之一,然后稳定了下来 大概原因:此种情况,jimdb极有可能某个分片的连 ...