实现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;     } }
阅读全文
0 0
原创粉丝点击