实现WinForm的DataGridView折叠功能(非原创,仅供收藏)
来源:互联网 发布:音响测试软件 编辑:程序博客网 时间:2024/06/07 00:23
说明:本文章是在学习WinForm过程中收藏的代码,非原创代码,仅用于学习,贴出的代码基本与原文章无异,稍作修改就实现了困扰我一年多的功能,这里要向原文章博主致谢。原文链接:http://blog.csdn.net/chenqiang920/article/details/52821727
C#的DataGridView是不支持分组以及折叠的,所以要实现此功能,就得扩展他的功能。
首先 添加扩展的Cell类
///
/// 可分组的单元格
///
public class DataGridViewGroupCell : DataGridViewTextBoxCell
{
#region Variant
/// <summary> /// 标示的宽度 /// </summary> const int PLUS_WIDTH = 24; /// <summary> /// 标示的区域 /// </summary> Rectangle groupPlusRect; #endregion #region Init public DataGridViewGroupCell() { groupLevel = 1; } #endregion #region Property int groupLevel; /// <summary> /// 组级别(以1开始) /// </summary> public int GroupLevel { get { return groupLevel; } set { groupLevel = value; } } DataGridViewGroupCell parentCell; /// <summary> /// 父节点 /// </summary> public DataGridViewGroupCell ParentCell { get { return parentCell; } set { if (value == null) throw new NullReferenceException("父节点不可为空"); if (!(value is DataGridViewGroupCell)) throw new ArgumentException("父节点必须为 DataGridViewGroupCell 类型"); parentCell = value; parentCell.AddChildCell(this); } } private bool collapsed; /// <summary> /// 是否收起 /// </summary> public bool Collapsed { get { return collapsed; } } private List<DataGridViewGroupCell> childCells = null; /// <summary> /// 所有的子结点 /// </summary> public DataGridViewGroupCell[] ChildCells { get { if (childCells == null) return null; return childCells.ToArray(); } } /// <summary> /// 取得组标示(有+或-号的框)的区域 /// </summary> public Rectangle GroupPlusRect { get { return groupPlusRect; } } bool bPaint = true; /// <summary> /// 是否重绘 /// </summary> public bool BPaint { get { return bPaint; } set { bPaint = value; } } #endregion #region 添加子节点 /// <summary> /// 添加子结点 /// </summary> /// <param name="cell"></param> /// <returns></returns> public int AddChildCell(DataGridViewGroupCell cell) { return AddChildCellRange(new DataGridViewGroupCell[] { cell }); } public int AddChildCellRange(DataGridViewGroupCell[] cells) { bool needRedraw = false; if (childCells == null) { //需要画一个加号 childCells = new List<DataGridViewGroupCell>(); needRedraw = true; } foreach (DataGridViewGroupCell cell in cells) { childCells.Add(cell); cell.groupLevel = groupLevel + 1; cell.parentCell = this; } if (needRedraw) DataGridView.InvalidateCell(this); return childCells.Count; } #endregion #region 绘制节点 protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { if (!bPaint) { base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); return; } Pen gridPen = new Pen(DataGridView.GridColor); Brush bruBK = new SolidBrush(cellStyle.BackColor); int width = groupLevel * PLUS_WIDTH; Rectangle rectLeft = new Rectangle(cellBounds.Left, cellBounds.Top - 1, width, cellBounds.Height); cellBounds.X += width; cellBounds.Width -= width; base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); PaintGroupPlus(graphics, gridPen, bruBK, cellStyle, rectLeft, collapsed); gridPen.Dispose(); gridPen = null; bruBK.Dispose(); bruBK = null; } private void PaintGroupPlus(Graphics graphics, Pen gridPen, Brush bruBK, DataGridViewCellStyle cellStyle, Rectangle rectLeft, bool collapsed) { Pen pen = new Pen(DataGridView.GridColor, 1); pen.DashStyle = DashStyle.Dot; graphics.FillRectangle(bruBK, rectLeft); int left = rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH; //画 Left, Top, Right 三根线 graphics.DrawLine(gridPen, left, rectLeft.Top, rectLeft.Right, rectLeft.Top);//上 graphics.DrawLine(gridPen, rectLeft.Right, rectLeft.Bottom, rectLeft.Left, rectLeft.Bottom); //最左边的一条线 graphics.DrawLine(gridPen, rectLeft.Left, rectLeft.Top, rectLeft.Right, rectLeft.Top); //如果是该级别的最后一个节点,则需要画一个底线,以便将整个组封闭起来 bool drawBottomLine = false; for (int i = 1; i < groupLevel; i++) { if (!ParentCell.IsLastCell(ParentCell.groupLevel))//上层不是最后一个节点 { graphics.DrawLine(pen, rectLeft.Left + (i - 1) * PLUS_WIDTH + PLUS_WIDTH / 2, rectLeft.Top , rectLeft.Left + (i - 1) * PLUS_WIDTH + PLUS_WIDTH / 2, rectLeft.Bottom); } } //如果有子结点, 则需要画一个方框, 里面有+号或-号 if (childCells != null && childCells.Count > 0) { groupPlusRect = new Rectangle((groupLevel - 1) * PLUS_WIDTH + rectLeft.Left + (PLUS_WIDTH - 12) / 2 , rectLeft.Top + (rectLeft.Height - 12) / 2, 12, 12); graphics.DrawRectangle(gridPen, groupPlusRect); graphics.DrawLine(Pens.Black, groupPlusRect.Left + 3, groupPlusRect.Top + groupPlusRect.Height / 2 , groupPlusRect.Right - 3, groupPlusRect.Top + groupPlusRect.Height / 2); if (collapsed) { graphics.DrawLine(Pens.Black, groupPlusRect.Left + groupPlusRect.Width / 2, groupPlusRect.Top + 3 , groupPlusRect.Left + groupPlusRect.Width / 2, groupPlusRect.Bottom - 3); } } else { //横 graphics.DrawLine(pen, rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH + PLUS_WIDTH / 2, rectLeft.Top + rectLeft.Height / 2 , rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH + PLUS_WIDTH, rectLeft.Top + rectLeft.Height / 2); //竖 if (!IsLastCell((groupLevel - 1))) { graphics.DrawLine(pen, rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH + PLUS_WIDTH / 2, rectLeft.Top , rectLeft.Left + (groupLevel - 1) * PLUS_WIDTH + PLUS_WIDTH / 2, rectLeft.Bottom); } else graphics.DrawLine(pen, (groupLevel - 1) * PLUS_WIDTH + rectLeft.Left + (PLUS_WIDTH - 8) / 2 + 4, rectLeft.Top + (rectLeft.Height - 8) / 2 - 6, (groupLevel - 1) * PLUS_WIDTH + rectLeft.Left + (PLUS_WIDTH - 8) / 2 + 4, rectLeft.Top + (rectLeft.Height - 8) / 2 + 4); } pen.Dispose(); pen = null; } #endregion #region 判断 /// <summary> /// 该节点是否为某一级节点的最后一个子结点 /// </summary> /// <param name="level">节点层级</param> /// <returns></returns> private bool IsLastCell(int level) { int row = DataGridView.Rows.GetNextRow(RowIndex, DataGridViewElementStates.None); if (row == -1) return true; DataGridViewGroupCell cel = DataGridView.Rows[row].Cells[0] as DataGridViewGroupCell; return (cel.GroupLevel == level); } #endregion #region 点击 Cell protected override void OnMouseDown(DataGridViewCellMouseEventArgs e) { Rectangle rect = DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, false); Point pt = new Point(rect.Left + e.Location.X, rect.Top + e.Location.Y); if (groupPlusRect.Contains(pt)) { if (collapsed) { Expand(); } else { Collapse(); } } base.OnMouseDown(e); } #endregion #region 展开/收起节点 /// <summary> /// 展开节点 /// </summary> public void Expand() { if (parentCell != null) { parentCell.CollapseAll(); } collapsed = false; ShowChild(true); base.DataGridView.InvalidateCell(this); } private void ShowChild(bool show) { if (childCells == null) return; foreach (DataGridViewGroupCell cel in childCells) { if (cel.RowIndex == -1) { continue; } DataGridView.Rows[cel.RowIndex].Visible = show; if (!cel.collapsed) cel.ShowChild(show); } } /// <summary> /// 收起节点 /// </summary> public void Collapse() { collapsed = true; ShowChild(false); base.DataGridView.InvalidateCell(this); } /// <summary> /// 展开节点及子结点 /// </summary> public void ExpandAll() { if (childCells == null) return; foreach (DataGridViewGroupCell cel in childCells) { cel.ExpandAll(); } } public void CollapseAll() { if (childCells == null) return; foreach (DataGridViewGroupCell cel in childCells) { cel.CollapseAll(); } } #endregion}
接着添加扩展的Column
///
/// 可分组的列 (该列必须是 Grid 的第一列)
///
public class DataGridViewGroupColumn : DataGridViewTextBoxColumn
{
public DataGridViewGroupColumn()
{
CellTemplate = new DataGridViewGroupCell();
ReadOnly = true;
}
public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if ((value != null) && !(value is DataGridViewGroupCell)) { throw new InvalidCastException("Need System.Windows.Forms.DataGridViewGroupCell"); } base.CellTemplate = value; } }}
接着添加扩展的的DataGridView
public class DefineDataGridView : DataGridView
{
bool showRowHeaderNumbers;
///
/// 是否显示行号
///
[Description(“是否显示行号”), DefaultValue(true)]
public bool ShowRowHeaderNumbers
{
get { return showRowHeaderNumbers; }
set
{
if (showRowHeaderNumbers != value)
Invalidate();
showRowHeaderNumbers = value;
}
}
public DefineDataGridView() { showRowHeaderNumbers = true; this.RowHeadersWidth = 30; this.AllowUserToAddRows = false; } }
- 实现WinForm的DataGridView折叠功能(非原创,仅供收藏)
- C# Winform DataGridView分页功能的实现
- DataGridView分页功能的实现收藏
- jquery-ul-li实现分页功能 转载仅供交流
- c++数据结构 笔记(多个博客组合,非原创,,仅供自己查编)
- gedit折叠功能的实现
- Winform中DataGridView的删除功能
- Winform折叠菜单实现
- Winform折叠菜单实现
- WinForm DataGridView分页功能
- 足迹二:Android客户端与PC服务端之间的SOCKET通讯实现登陆功能(客户端 仅供学习)
- Winform传统DataGridView和DevExpress控件的GridControl两者表头全选功能的实现
- scintilla 中的代码折叠功能的使用收藏
- scintilla 中的代码折叠功能的使用收藏
- scintilla 中的代码折叠功能的使用收藏
- WinForm下DataGridView导出Excel的实现
- C#WINFORM 的DATAGRIDVIEW多表头实现
- 收藏一些比较牛逼的博客地址,仅供自己参考。
- cron表达式
- React Native 报错 Could not get BatchedBridge, make sure your bundle is packaged correctly.
- springMVC+Spring+Mybatis控制台输出sql,配置log4j.properties文件
- POI+JFreeChart生成报表图片插入到Excel中
- Apache Storm 开发 零基础入门
- 实现WinForm的DataGridView折叠功能(非原创,仅供收藏)
- 鸟哥的LINUX私房菜第二章 学习笔记
- makefile 中=与:=的差别
- bzoj1589 [Usaco2008 Dec]Trick or Treat on the Farm 采集糖果(tarjan缩点+记忆化搜索)
- 初识Spark2.0之Spark SQL
- oms项目常用执行sql方法(增删改查)持续更新
- 最详细的Storm入门教程(一)
- Tensorflow中的4要素(7)---《深度学习》
- 黑白翻转棋算法java实现