实现WinForm的DataGridView折叠功能(非原创,仅供收藏)

说明:本文章是在学习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; 
    } 
}
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值