官网

http://www.hzhcontrols.com

前提

入行已经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自定义控件-基类控件

开始

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

  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的更多相关文章

  1. (四十四)c#Winform自定义控件-水波-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  2. (四)c#Winform自定义控件-选择按钮组

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  3. (二十四)c#Winform自定义控件-单标题窗体

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  4. (四十)c#Winform自定义控件-开关-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  5. (十四)c#Winform自定义控件-键盘(一)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  6. (五十四)c#Winform自定义控件-仪表盘

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  7. (六十四)c#Winform自定义控件-温度计(工业)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  8. (七十四)c#Winform自定义控件-金字塔图表

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  9. (八十四)c#Winform自定义控件-导航菜单(类Office菜单)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  10. (四十六)c#Winform自定义控件-水波进度条-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

随机推荐

  1. webpack学习2.3webpack核心概念

    核心概念(四个) Entry(入口) Output(出口) Loaders()来处理其他类型的资源文件 Plugins(插件) 1.入口(Entry) 作用:代码的入口,打包的入口,单个或多个, 示例 ...

  2. django基础之day05,orm字段参数,自定义需要的字段,orm中的事务操作

    orm字段和参数 charfield varchar integerfield int bigintegerfield bigint emailfield varchar(254) datefield ...

  3. mysql之行转列与列转行

    mysql之行转列与列转行是数据查询的常见操作,以更好的来展示数据,下面就详细说说怎么实现. 行转列 行转列的话,就是将一条一条的行数据记录转换为一条列数据展示,一般来说是根据某一列来做汇总数据的操作 ...

  4. sqlalchemy 执行原生sql语句

    from contextlib import contextmanager from sqlalchemy import create_engine, ForeignKey from sqlalche ...

  5. 一起学SpringMVC之国际化

    随着网络的发展,在Web开发中,系统的国际化需求已经变得非常的普遍.本文主要讲解SpringMVC框架对多语言的支持,仅供学习分享使用,如有不足之处,还请指正. 什么是国际化? 国际化(interna ...

  6. How to: Calculate a Property Value Based on Values from a Detail Collection 如何:基于详细信息集合中的值计算属性值

    This topic describes how to implement a business class, so that one of its properties is calculated ...

  7. JDK性能分析工具-引用于深入理解JVM

    1.jps(JVM Process Status Tool) 列出正在运行的虚拟机进程. 2.jstat(JVM Statistics Monitoring Tool) 显示运行状态信息. 3.jin ...

  8. Java学习笔记--线程day01

    线程的概念:一个线程是进程的顺序执行流: 同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈.线程在切换时负荷小,因此,线程也被称为轻负荷进程.一个进程中可以有多个线程. ...

  9. 如何抓取 framework input 事件相关 log

    出现事件输入相关的问题时, 建议先 followhttp://429564140.iteye.com/blog/2355405来检测对应的设备是否有响应输入 如果没有响应输入,则可能是 driver ...

  10. centos7设置静态ip-修改配置文件方式

    修改IP地址为静态地址需要修改配置文件,首先打开配置文件,在控制台输入cd /etc/sysconfig/network-scripts 输入ifconfig,这样就可以看到你的ip地址等信息了. v ...