自定义TreeDataView 控件,百万级别数据秒绘。

最近需要使用到数据展现,需要对数据折叠展现。网上找了许多控件,如:TreeListView,TreevDataGirdView等,但是都无法到达效果,而且加载百万条数据时,绘制灰常的卡顿。

话不多说。先上效果图

 

 

1 准备工作,创建两个类,用户绘制行与列

  public class UserRow
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="level">节点等级</param>
        public UserRow(int level)
        {
            _level = level;
            strFmt.Alignment = StringAlignment.Near; //文本水平居中
            strFmt.LineAlignment = StringAlignment.Center; //文本垂直居中
        }

        int _level = 0;

        public int Level
        {
            get { return _level; }
        }

        public UserRow Parent { get; set; } = null;

        public float PointX = 0;

        public float PointY = 0;


        //public float RowHeigth = 20;

        public bool ExpandEvent = false;

        private bool _expand = false;

        public bool Expand
        {
            get { return _expand; }
            set { _expand = value; }
        }

        private float _marginLeft = 30;
        public float MarginLeft
        {
            get
            {
                return _marginLeft;
            }
        }

        public bool IsSelected = false;

        public List<UserCell> Cells = new List<UserCell>();

        List<UserRow> _subrows = new List<UserRow>();
        public List<UserRow> SubRows
        {
            get { return _subrows; }
        }


        StringFormat strFmt = new System.Drawing.StringFormat();
        Font myFont = new Font("宋体", 10);
        public float Draw(Graphics g, float dx, float dy, float MapLocationX, float MapLocationY, float h, float w, List<UserCell> colums)
        {
            PointY = dy;
            float margleft = calcMarginLeft(this);
            float x = PointX - MapLocationX ;
            float y = PointY - MapLocationY;

            if (_level == 0)
            {
                g.FillRectangle(Brushes.LightSkyBlue, x, y + 1, w - 2, h - 1);
            }
            else
            {
                g.FillRectangle(Brushes.White, x, y + 1, w - 2, h - 1);
            }
            if (this.SubRows.Count > 0)
            {
                RectangleF plusRect = new RectangleF(x + margleft - 15, y + 5, 10, 10);// +-号的大小 是9 * 9
                g.FillRectangle(Brushes.White, plusRect);
                g.DrawRectangle(new Pen(Brushes.Black), plusRect.X, plusRect.Y, plusRect.Width, plusRect.Height);
                if (this.Expand)
                {
                    g.DrawString("-", new Font("宋体", 9), Brushes.Black, plusRect);
                }
                else
                {
                    g.DrawString("+", new Font("宋体", 9), Brushes.Black, plusRect);
                }
            }

            float startPointX = x + margleft ;
            for (int i = 0; i < colums.Count; i++)
            {
                if (colums[i].IsViszble && i< Cells.Count)
                {
                    RectangleF rf = new RectangleF(startPointX, y + 1, colums[i].Width, h - 1);
                    if (colums[i].IsSelect)
                    {
                        g.FillRectangle(Brushes.Black, rf);
                        g.DrawString(Cells[i].Value, myFont, Brushes.White, rf, strFmt);
                    }
                    else
                    {
                        g.FillRectangle(Brushes.Transparent, rf);
                        g.DrawString(Cells[i].Value, myFont, Brushes.Black, rf, strFmt);
                    }
                    //g.DrawLine(new Pen(Brushes.White, 1), startPointX, y, startPointX, y + h);

                    startPointX += colums[i].Width;
                }

            }

            Pen mypen;
            if (IsSelected)
            {
                mypen = new Pen(Brushes.Red, 1);
                g.DrawRectangle(mypen, x, y + 1, w -2, h - 1);
            }
            else
            {
                mypen = new Pen(Brushes.White, 1);
                g.DrawRectangle(mypen, x, y + 1,w -2, h - 1);
            }

            


            return startPointX + margleft;
        }

        public float CalcMaxWidth()
        {
            float width = PointX;
            float margleft = calcMarginLeft(this);
            for (int i = 0; i < Cells.Count; i++)
            {
                width += Cells[i].Width;
            }
            return width + margleft;
        }
        public float calcMarginLeft(UserRow row)
        {
            return (row.Level + 1) * row.MarginLeft;
            //if (row.Parent != null)
            //{
            //    float t = calcMarginLeft(row.Parent);
            //    return row.Parent.MarginLeft + t;
            //}
            //else
            //{
            //    return row.MarginLeft;
            //}
        }

        public bool IsSelect(float dx, float dy, float h, float w)
        {
            float margleft = calcMarginLeft(this);
            
            ExpandEvent = false;
            if (dx <= PointX + w && dx >= PointX && dy <= PointY + h && dy >= PointY)
            {
                IsSelected = true;
                RectangleF plusRect = new RectangleF(PointX + margleft - 15, PointY + 5, 10, 10);// +-号的大小 是9 * 9
                if (dx <= plusRect.X + plusRect.Width && dx >= plusRect.X && dy <= plusRect.Y + plusRect.Height && dy >= plusRect.Y)
                {
                    _expand = !_expand;
                    ExpandEvent = true;

                }
            }
            else
            {
                IsSelected = false;
            }
            
            return IsSelected;


        }

    }

    public class UserCell
    {
        /// <summary>
        /// 当前值
        /// </summary>
        public string Value { get; set; }
        /// <summary>
        /// 默认单元格宽度
        /// </summary>
        public float Width { get; set; } = 80;
        /// <summary>
        /// 是否显示
        /// </summary>
        public bool IsViszble { get; set; } = true;
        /// <summary>
        /// 是否选中单元格
        /// </summary>
        public bool IsSelect { get; set; } = false;


    }

 

 

2 添加用户控件,然后在控件上面添加 三个控件,PictureBox,vScrollBar1,hScrollBar1

PictureBox 用于绘制数据,vScrollBar1,hScrollBar1用于移动数据

设计代码

namespace UserTreeTable
{
    partial class UserControl1
    {
        /// <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.components = new System.ComponentModel.Container();
            this.vScrollBar1 = new System.Windows.Forms.VScrollBar();
            this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
            this.pbImg = new System.Windows.Forms.PictureBox();
            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.折叠ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.折叠层一ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.折叠层二ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.展开ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.展开层一ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.展开层二ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            ((System.ComponentModel.ISupportInitialize)(this.pbImg)).BeginInit();
            this.contextMenuStrip1.SuspendLayout();
            this.SuspendLayout();
            // 
            // vScrollBar1
            // 
            this.vScrollBar1.Dock = System.Windows.Forms.DockStyle.Right;
            this.vScrollBar1.Location = new System.Drawing.Point(439, 0);
            this.vScrollBar1.Name = "vScrollBar1";
            this.vScrollBar1.Size = new System.Drawing.Size(17, 325);
            this.vScrollBar1.TabIndex = 0;
            this.vScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.vScrollBar1_Scroll);
            this.vScrollBar1.ValueChanged += new System.EventHandler(this.vScrollBar1_ValueChanged);
            // 
            // hScrollBar1
            // 
            this.hScrollBar1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.hScrollBar1.Location = new System.Drawing.Point(0, 308);
            this.hScrollBar1.Name = "hScrollBar1";
            this.hScrollBar1.Size = new System.Drawing.Size(439, 17);
            this.hScrollBar1.TabIndex = 1;
            this.hScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hScrollBar1_Scroll);
            this.hScrollBar1.ValueChanged += new System.EventHandler(this.hScrollBar1_ValueChanged);
            // 
            // pbImg
            // 
            this.pbImg.BackColor = System.Drawing.SystemColors.Control;
            this.pbImg.ContextMenuStrip = this.contextMenuStrip1;
            this.pbImg.Dock = System.Windows.Forms.DockStyle.Fill;
            this.pbImg.Location = new System.Drawing.Point(0, 0);
            this.pbImg.Name = "pbImg";
            this.pbImg.Size = new System.Drawing.Size(439, 308);
            this.pbImg.TabIndex = 2;
            this.pbImg.TabStop = false;
            this.pbImg.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
            this.pbImg.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
            this.pbImg.Resize += new System.EventHandler(this.pbImg_Resize);
            // 
            // contextMenuStrip1
            // 
            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.折叠ToolStripMenuItem,
            this.展开ToolStripMenuItem});
            this.contextMenuStrip1.Name = "contextMenuStrip1";
            this.contextMenuStrip1.Size = new System.Drawing.Size(153, 70);
            // 
            // 折叠ToolStripMenuItem
            // 
            this.折叠ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.折叠层一ToolStripMenuItem,
            this.折叠层二ToolStripMenuItem});
            this.折叠ToolStripMenuItem.Name = "折叠ToolStripMenuItem";
            this.折叠ToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
            this.折叠ToolStripMenuItem.Text = "折叠";
            // 
            // 折叠层一ToolStripMenuItem
            // 
            this.折叠层一ToolStripMenuItem.Name = "折叠层一ToolStripMenuItem";
            this.折叠层一ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
            this.折叠层一ToolStripMenuItem.Text = "折叠层一";
            this.折叠层一ToolStripMenuItem.Click += new System.EventHandler(this.折叠层一ToolStripMenuItem_Click);
            // 
            // 折叠层二ToolStripMenuItem
            // 
            this.折叠层二ToolStripMenuItem.Name = "折叠层二ToolStripMenuItem";
            this.折叠层二ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
            this.折叠层二ToolStripMenuItem.Text = "折叠层二";
            this.折叠层二ToolStripMenuItem.Click += new System.EventHandler(this.折叠层二ToolStripMenuItem_Click);
            // 
            // 展开ToolStripMenuItem
            // 
            this.展开ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.展开层一ToolStripMenuItem,
            this.展开层二ToolStripMenuItem});
            this.展开ToolStripMenuItem.Name = "展开ToolStripMenuItem";
            this.展开ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.展开ToolStripMenuItem.Text = "展开";
            // 
            // 展开层一ToolStripMenuItem
            // 
            this.展开层一ToolStripMenuItem.Name = "展开层一ToolStripMenuItem";
            this.展开层一ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.展开层一ToolStripMenuItem.Text = "展开层一";
            this.展开层一ToolStripMenuItem.Click += new System.EventHandler(this.展开层一ToolStripMenuItem_Click);
            // 
            // 展开层二ToolStripMenuItem
            // 
            this.展开层二ToolStripMenuItem.Name = "展开层二ToolStripMenuItem";
            this.展开层二ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.展开层二ToolStripMenuItem.Text = "展开层二";
            this.展开层二ToolStripMenuItem.Click += new System.EventHandler(this.展开层二ToolStripMenuItem_Click);
            // 
            // UserControl1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.pbImg);
            this.Controls.Add(this.hScrollBar1);
            this.Controls.Add(this.vScrollBar1);
            this.Name = "UserControl1";
            this.Size = new System.Drawing.Size(456, 325);
            this.Resize += new System.EventHandler(this.UserControl1_Resize);
            ((System.ComponentModel.ISupportInitialize)(this.pbImg)).EndInit();
            this.contextMenuStrip1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.VScrollBar vScrollBar1;
        private System.Windows.Forms.HScrollBar hScrollBar1;
        private System.Windows.Forms.PictureBox pbImg;
        private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
        private System.Windows.Forms.ToolStripMenuItem 折叠ToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem 折叠层一ToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem 折叠层二ToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem 展开ToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem 展开层一ToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem 展开层二ToolStripMenuItem;
    }
}

 

3  在自定义控件UserControl1中实现绘制

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace UserTreeTable
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1(List<UserRow> rows)
        {
            InitializeComponent();

            this.Load += UserControl1_Load;
            this.pbImg.MouseWheel += PbImg_MouseWheel;
            Rows = rows;
        }

       /// <summary>
       /// 所有行
       /// </summary>
        public List<UserRow> Rows = new List<UserRow>();

        /// <summary>
        /// 所有列
        /// </summary>
        public SortedList<int, UserRow> HeadColumns = new SortedList<int, UserRow>();

        /// <summary>
        /// 选中的列
        /// </summary>
        List<UserCell> selectHeadColumns = new List<UserCell>();


        /// <summary>
        /// 选中行
        /// </summary>
        UserRow _selectRow;

        /// <summary>
        /// 图像平移后横坐标偏移的像素
        /// </summary>
        public float MapLocationX = 0;
        /// <summary>
        ///  图像平移后纵坐标偏移的像素
        /// </summary>
        public float MapLocationY = 0;

        /// <summary>
        /// 固定行号
        /// </summary>
        const int rowHeight = 20;
        /// <summary>
        /// 默认行宽
        /// </summary>
        float rowWidth = 100;

        //float MaxHeight = 0;
        //float MaxWidth = 0;

        private void UserControl1_Load(object sender, EventArgs e)
        {
            CalcMapSize();
            if (Rows.Count > 0)
                _selectRow = Rows[0];
        }

        private void PbImg_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
            {
                if (vScrollBar1.Value - rowHeight > 0)
                {
                    vScrollBar1.Value -= rowHeight;
                }
                else
                {
                    vScrollBar1.Value = vScrollBar1.Minimum;
                }

            }
            else
            {
                if (vScrollBar1.Value + rowHeight < vScrollBar1.Maximum)
                {
                    vScrollBar1.Value += rowHeight;
                }
                else
                {
                    vScrollBar1.Value = vScrollBar1.Maximum;
                }
            }
            if (MapLocationY != vScrollBar1.Value)
            {
                MapLocationY = vScrollBar1.Value;
                pbImg.Refresh();
            }

        }



        public void CalcMapSize()
        {
            float w = 0, h = 0;
            foreach (UserRow c1 in HeadColumns.Values)
            {
                float w1 = c1.CalcMaxWidth();
                if (w < w1)
                {
                    w = w1;
                }
                
            }
            rowWidth = w;
            if (rowWidth > pbImg.Width)
            {
                hScrollBar1.Enabled = true;
                hScrollBar1.Minimum = 0;
                hScrollBar1.Maximum = (int)rowWidth - pbImg.Width +10;
                hScrollBar1.LargeChange = 10;
                hScrollBar1.SmallChange = 10;
            }
            else
            {
                rowWidth = pbImg.Width;
                MapLocationX = 0;
                hScrollBar1.Enabled = false;
                //hScrollBar1.Visible = false;
            }

            foreach (UserRow u1 in Rows)
            {
                h += rowHeight;              
                if(u1.Expand)
                {
                    foreach (UserRow u2 in u1.SubRows)
                    {
                        h += rowHeight;
                       
                        if (u2.Expand)
                        {
                            foreach (UserRow u3 in u2.SubRows)
                            {
                                h += rowHeight;
                                
                            }
                        }
                    }
                }
            }
            

            int vscrollmaxNum = (int)h - pbImg.Height + 20;
            if (vscrollmaxNum != vScrollBar1.Maximum)
            {
                if (h > pbImg.Height)
                {
                    vScrollBar1.Enabled = true;
                    vScrollBar1.Minimum = 0;
                    vScrollBar1.Maximum = vscrollmaxNum;
                    vScrollBar1.LargeChange = rowHeight;
                    vScrollBar1.SmallChange = rowHeight;
                    
                }
                else
                {
                    MapLocationY = 0;
                    vScrollBar1.Enabled = false;
                }

            }
            
           
            
        }


        void Drawing(Graphics g)
        {
            float pointX = 0;
            float pointY = rowHeight;
            float scrollY = this.vScrollBar1.Value;
            //float tempHeight = scrollY + this.panel2.ClientSize.Height;
            float tempHeight = this.vScrollBar1.Value + pbImg.Height;
            
            foreach (UserRow u1 in Rows)
            {
                if (pointY <= tempHeight && pointY >= scrollY)
                {
                    u1.Draw(g, pointX, pointY, MapLocationX, MapLocationY, rowHeight, rowWidth, HeadColumns[u1.Level].Cells);
                }

                pointY += rowHeight;

                if (u1.Expand == true)
                {
                    foreach (UserRow u2 in u1.SubRows)
                    {
                        if (pointY <= tempHeight && pointY >= scrollY)
                        {
                            u2.Draw(g, pointX, pointY, MapLocationX, MapLocationY, rowHeight, rowWidth, HeadColumns[u2.Level].Cells);
                        }

                        pointY += rowHeight;
                        if (u2.Expand)
                        {
                            foreach (UserRow u3 in u2.SubRows)
                            {
                                if (pointY <= tempHeight && pointY >= scrollY)
                                {
                                    u3.Draw(g, pointX, pointY, MapLocationX, MapLocationY, rowHeight, rowWidth, HeadColumns[u3.Level].Cells);
                                }

                                pointY += rowHeight;
                            }
                        }
                    }
                }
            }

        }

        void DrawHead(Graphics g)
        {
            StringFormat strFmt = new System.Drawing.StringFormat();
            strFmt.Alignment = StringAlignment.Near; //文本水平居中
            strFmt.LineAlignment = StringAlignment.Center; //文本垂直居中

            Rectangle rect = new Rectangle(0, 0, (int)rowWidth + 10, rowHeight);
            Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(rect, Color.Gray, Color.LightGray, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
            g.FillRectangle(b, rect);

            if (_selectRow != null)
            {
                float margleft = _selectRow.calcMarginLeft(_selectRow);
                float startPointX = margleft - MapLocationX;
                UserRow headrow = HeadColumns[_selectRow.Level];
                foreach (UserCell c in headrow.Cells)
                {
                    RectangleF rf = new RectangleF(startPointX, 2, c.Width, rowHeight - 1);
                    if (c.IsSelect)
                    {
                        g.FillRectangle(Brushes.Black, rf);
                        g.DrawString(c.Value, this.Font, Brushes.White, rf, strFmt);
                    }
                    else
                    {
                        g.FillRectangle(Brushes.Transparent, rf);
                        g.DrawString(c.Value, this.Font, Brushes.Black, rf, strFmt);
                    }
                    g.DrawLine(new Pen(Brushes.White, 1), startPointX, 0, startPointX, rowHeight);

                    startPointX += c.Width;
                }
                g.DrawLine(new Pen(Brushes.White, 1), startPointX, 0, startPointX, rowHeight);
            }

        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Drawing(g);
            DrawHead(g);
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                float y = e.Y;
                if (e.Y < rowHeight)
                {
                    UserCell headcell = SelectHeadIndex(e.X, e.Y);
                    if (headcell != null)
                    {
                        this.pbImg.Refresh();
                    }
                }
                else
                {
                    UserRow tempselectRow = SelectRow(e.X + MapLocationX, e.Y + MapLocationY);
                    if (tempselectRow != null)
                    {
                        if (tempselectRow != _selectRow)
                        {
                            if (_selectRow != null)
                            {
                                _selectRow.IsSelected = false;
                                if (tempselectRow.Level != _selectRow.Level)
                                {
                                    foreach (UserCell c in HeadColumns[_selectRow.Level].Cells)
                                    {
                                        c.IsSelect = false;
                                    }
                                }
                            }
                        }
                        _selectRow = tempselectRow;
                        if (tempselectRow.ExpandEvent)
                        {
                            CalcMapSize();

                        }
                        this.pbImg.Refresh();
                    }
                }

            }
        }

        UserCell SelectHeadIndex(float x, float y)
        {
            if (_selectRow != null)
            {
                UserRow headrow = HeadColumns[_selectRow.Level];
                if (headrow != null)
                {
                    float margleft = _selectRow.calcMarginLeft(_selectRow);
                    float startPointX = margleft - MapLocationX;
                    foreach (UserCell c in headrow.Cells)
                    {                       
                        if (x >= startPointX && x <= startPointX + c.Width && y > 0 && y < rowHeight)
                        {
                            c.IsSelect = !c.IsSelect;
                            return c;
                        }
                        startPointX += c.Width;
                    }
                }
            }
            return null;
        }
        UserRow SelectRow(float x, float y)
        {
            Console.WriteLine("选择坐标:x= " + x + " y= " + y);
            
            foreach (UserRow u1 in Rows)
            {
                if (u1.IsSelect(x, y, rowHeight, rowWidth))
                {
                    return u1;
                }
                else if (u1.Expand == true)
                {
                    foreach (UserRow u2 in u1.SubRows)
                    {
                        if (u2.IsSelect(x, y, rowHeight, rowWidth))
                        {
                            return u2;
                        }
                        else if (u2.Expand)
                        {
                            foreach (UserRow u3 in u2.SubRows)
                            {
                                if (u3.IsSelect(x, y, rowHeight, rowWidth))
                                {
                                    return u3;
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }

        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            //System.Threading.Thread.Sleep(5);
            //MapLocationY = e.OldValue;
            //Console.WriteLine("old:" + e.OldValue);
            //Console.WriteLine("new:"+e.NewValue);
            //this.pbImg.Refresh();
            
        }

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            //MapLocationX = e.NewValue;
            //Console.WriteLine("new:" + e.NewValue);
            //this.pbImg.Refresh();
        }

        private void UserControl1_Resize(object sender, EventArgs e)
        {
        }

        private void pbImg_Resize(object sender, EventArgs e)
        {
            CalcMapSize();
            this.pbImg.Refresh();
        }

        private void vScrollBar1_ValueChanged(object sender, EventArgs e)
        {
            MapLocationY = vScrollBar1.Value;
            this.pbImg.Refresh();
        }

        private void hScrollBar1_ValueChanged(object sender, EventArgs e)
        {
            MapLocationX = hScrollBar1.Value;
            this.pbImg.Refresh();
        }

        private void 折叠层一ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (UserRow u1 in Rows)
            {
                u1.Expand = false;
                
            }
            if (_selectRow != null && _selectRow.Level!= 0)
            {
                _selectRow.Expand = false;
            }
            CalcMapSize();
            this.pbImg.Refresh();
        }

        private void 折叠层二ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (UserRow u1 in Rows)
            {
                foreach (UserRow u2 in u1.SubRows)
                {
                    u2.Expand = false;
                    //foreach (UserRow u3 in u2.SubRows)
                    //{

                    //}
                }

            }
            if (_selectRow != null && _selectRow.Level > 1)
            {
                _selectRow.Expand = false;
            }
            CalcMapSize();
            this.pbImg.Refresh();
        }

        

        private void 展开层一ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (UserRow u1 in Rows)
            {
                u1.Expand = true;
               

            }
            CalcMapSize();
            this.pbImg.Refresh();
        }

        private void 展开层二ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (UserRow u1 in Rows)
            {
                u1.Expand = true;
                foreach (UserRow u2 in u1.SubRows)
                {
                    u2.Expand = true;
                    //foreach (UserRow u3 in u2.SubRows)
                    //{

                    //}
                }

            }
            CalcMapSize();
            this.pbImg.Refresh();
        }
    }
}

 

4 最后在FORM界面中使用

首先需要生成数据源

public List<UserRow> Rows = new List<UserRow>();

        SortedList<int, UserRow> HeadColumns = new SortedList<int, UserRow>();

void BuildData()
        {
            for (int i = 0; i < 100; i++)
            {
                UserRow u1 = Packdata(0, i.ToString());
                u1.Expand = true;
                for (int j = 0; j < 5; j++)
                {
                    UserRow u2 = Packdata(1, i.ToString() + "-" + j.ToString());
                    u2.Parent = u1;
                    u2.Expand = true;
                    u1.SubRows.Add(u2);

                    for (int k = 0; k < 200; k++)
                    {
                        UserRow u3 = Packdata(2, i.ToString() + "-" + j.ToString() + "-" + k.ToString());
                        u3.Parent = u2;
                        u2.SubRows.Add(u3);
                    }
                }

                Rows.Add(u1);
            }

            HeadColumns.Add(0, PackHead(0));
            HeadColumns.Add(1, PackHead(1));
            HeadColumns.Add(2, PackHead(2));
        }

UserRow Packdata(int level, string index)
        {
            UserRow u = new UserRow(level);
            for (int i = 0; i < 10; i++)
            {
                UserCell cell = new UserCell();
                cell.Value = index + "-" + i.ToString();
                u.Cells.Add(cell);
            }

            return u;
        }

        UserRow PackHead(int level)
        {
            UserRow u = new UserRow(level);
            for (int i = 0; i < 10; i++)
            {
                UserCell cell = new UserCell();
                cell.Value = "" + level + "-" + i;
                u.Cells.Add(cell);
            }

            return u;
        }

 

最后把控件添加到form窗体中

private void Form2_Load(object sender, EventArgs e)
        {
            BuildData();
            UserControl1 uct = new UserControl1(Rows);
            uct.HeadColumns = HeadColumns;
            this.Controls.Add(uct);
            uct.Dock = DockStyle.Fill;
        }

 

DEMO代码虽然比较粗糙,但是不影响使用。

转载麻烦指明出处。。。

 

posted on 2020-12-02 15:34  永恒921  阅读(302)  评论(0编辑  收藏  举报