如何使用可调整大小的单元格来制作TableLayoutPanel,例如使用Splitter

时间:2015-06-26 09:20:30

标签: c# winforms tablelayoutpanel splitter

获得了包含1列和N行的TableLayoutPanel 细胞需要像细胞之间的分裂器组件一样可以调整大小。 不使用SplitContainer。

没有TableLayoutPanel可能是其他想法吗?

3 个答案:

答案 0 :(得分:6)

这实际上取决于你想用它做什么:DataGridView带来了交互性,但它的细胞既不是控制也不是容器..

您可以尝试这个TableLayoutPanel子类是否符合您的要求:

public partial class SplitTablePanel : TableLayoutPanel
{
    public int SplitterSize { get; set; }

    int sizingRow = -1;
    int currentRow = -1;
    Point mdown = Point.Empty;
    int oldHeight = -1;
    bool isNormal = false;
    List<RectangleF> TlpRows = new List<RectangleF>();
    int[] rowHeights = new int[0];

    public SplitTablePanel()
    {
        InitializeComponent();
        this.MouseDown += SplitTablePanel_MouseDown;
        this.MouseMove += SplitTablePanel_MouseMove;
        this.MouseUp += SplitTablePanel_MouseUp;
        this.MouseLeave += SplitTablePanel_MouseLeave;
        SplitterSize = 6;
    }

    void SplitTablePanel_MouseLeave(object sender, EventArgs e)
    {
        Cursor = Cursors.Default;
    }


    void SplitTablePanel_MouseUp(object sender, MouseEventArgs e)
    {
        getRowRectangles(SplitterSize);
    }

    void SplitTablePanel_MouseMove(object sender, MouseEventArgs e)
    {
        if (!isNormal) nomalizeRowStyles();
        if (TlpRows.Count <= 0) getRowRectangles(SplitterSize);
        if (rowHeights.Length <= 0) rowHeights = GetRowHeights();

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (sizingRow < 0) return;
            int newHeight = oldHeight + e.Y - mdown.Y;
            sizeRow(sizingRow, newHeight);
        }
        else
        {
            currentRow = -1;
            for (int i = 0; i < TlpRows.Count; i++)
                if (TlpRows[i].Contains(e.Location)) { currentRow = i; break;}
            Cursor = currentRow >= 0 ? Cursors.SizeNS : Cursors.Default;
        }
    }

    void SplitTablePanel_MouseDown(object sender, MouseEventArgs e)
    {
        mdown = Point.Empty;
        sizingRow = -1;
        if (currentRow < 0) return;
        sizingRow = currentRow;
        oldHeight = rowHeights[sizingRow];
        mdown = e.Location;
    }


    void getRowRectangles(float size)
    {   // get a list of mouse sensitive rectangles
        float sz = size / 2f;
        float y = 0f;
        int w = ClientSize.Width;
        int[] rw = GetRowHeights();

        TlpRows.Clear();
        for (int i = 0; i < rw.Length - 1; i++)
        {
            y += rw[i];
            TlpRows.Add(new RectangleF(0, y - sz, w, size));
        }

    }

    void sizeRow(int row, int newHeight)
    {   // change the height of one row
        if (newHeight == 0) return;
        if (sizingRow < 0) return;
        SuspendLayout();
        rowHeights = GetRowHeights();
        if (sizingRow >= rowHeights.Length) return;

        if (newHeight > 0) 
            RowStyles[sizingRow] = new RowStyle(SizeType.Absolute, newHeight);
        ResumeLayout();
        rowHeights = GetRowHeights();
        getRowRectangles(SplitterSize);
    }

    void nomalizeRowStyles()
    {   // set all rows to absolute and the last one to percent=100!
        if (rowHeights.Length <= 0) return;
        rowHeights = GetRowHeights();
        RowStyles.Clear();
        for (int i = 0; i < RowCount - 1; i++)
        {
            RowStyle cs = new RowStyle(SizeType.Absolute, rowHeights[i]);
            RowStyles.Add(cs);
        }
        RowStyles.Add ( new RowStyle(SizeType.Percent, 100) );
        isNormal = true;
    }
}
}

答案 1 :(得分:5)

除了TaW的最佳答案之外,还有一种方法可以调整行和列的大小,并关闭控件调整大小时出现的小错误( - &gt;在TaW&#39; s代码分割器矩形也没有调整大小。)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace SomeNameSpace.Controls
{   
    public partial class SplitTableLayoutPanel : TableLayoutPanel
    {
        public int SplitterSize { get; set; }

        int sizingRow = -1;
        int currentRow = -1;
        Point mdown = Point.Empty;
        int oldHeight = -1;
        bool isNormalRow = false;
        List<RectangleF> tlpRows = new List<RectangleF>();
        int[] rowHeights = new int[0];

        int sizingCol = -1;
        int currentCol = -1;
        int oldWidth = -1;
        bool isNormalCol = false;
        List<RectangleF> tlpCols = new List<RectangleF>();
        int[] colWidths = new int[0];

        public SplitTableLayoutPanel()
        {
            InitializeComponent();
            this.MouseDown += SplitTablePanel_MouseDown;
            this.MouseMove += SplitTablePanel_MouseMove;
            this.MouseUp += SplitTablePanel_MouseUp;
            this.MouseLeave += SplitTablePanel_MouseLeave;
            this.Resize += SplitTablePanel_Resize;
            SplitterSize = 6;
        }

        void SplitTablePanel_Resize(object sender, EventArgs e)
        {
            getRowRectangles(SplitterSize);
            getColRectangles(SplitterSize);
        }
        void SplitTablePanel_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }


        void SplitTablePanel_MouseUp(object sender, MouseEventArgs e)
        {
            getRowRectangles(SplitterSize);
            getColRectangles(SplitterSize);
        }

        void SplitTablePanel_MouseMove(object sender, MouseEventArgs e)
        {
            bool r = rowMove(sender, e);
            bool c = colMove(sender, e);    

            if (r && !c)
                Cursor = Cursors.SizeNS;
            else if (!r && c)
                Cursor = Cursors.SizeWE;
            else if (r && c)
                Cursor = Cursors.SizeAll;
            else
                Cursor = Cursors.Default;
        }

        bool rowMove(object sender, MouseEventArgs e)
        {
            bool isMove = false;
            if (!isNormalRow) nomalizeRowStyles();
            if (tlpRows.Count <= 0) getRowRectangles(SplitterSize);
            if (rowHeights.Length <= 0) rowHeights = GetRowHeights();

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (sizingRow < 0) return false;
                int newHeight = oldHeight + e.Y - mdown.Y;
                sizeRow(sizingRow, newHeight);
                isMove = true;
            }
            else
            {
                currentRow = -1;
                for (int i = 0; i < tlpRows.Count; i++)
                if (tlpRows[i].Contains(e.Location)) 
                { 
                    currentRow = i;
                    isMove = true;
                    break;
                }
            }
            return isMove;
        }

        bool colMove(object sender, MouseEventArgs e)
        {
            bool isMove = false;
            if (!isNormalCol) nomalizeColStyles();
            if (tlpCols.Count <= 0) getColRectangles(SplitterSize);
            if (colWidths.Length <= 0) colWidths = GetColumnWidths();

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (sizingCol < 0) return false;
                int newWidth = oldWidth + e.X - mdown.X;
                sizeCol(sizingCol, newWidth);
                isMove = true;
            }
            else
            {
                currentCol = -1;
                for (int i = 0; i < tlpCols.Count; i++)
                if (tlpCols[i].Contains(e.Location)) 
                {
                    currentCol = i; 
                    isMove = true;
                    break;
                }
            }
            return isMove;
        }

        void SplitTablePanel_MouseDown(object sender, MouseEventArgs e)
        {
            mdown = Point.Empty;
            rowDown();   
            colDown();
            mdown = e.Location;
        }

        void rowDown()
        {
            sizingRow = -1;
            if (currentRow < 0) return;
            sizingRow = currentRow;
            oldHeight = rowHeights[sizingRow];
        }

        void colDown()
        {
            sizingCol = -1;
            if (currentCol < 0) return;
            sizingCol = currentCol;
            oldWidth = colWidths[sizingCol];
        }


        void getRowRectangles(float size)
        {   // get a list of mouse sensitive rectangles
            float sz = size / 2f;
            float y = 0f;
            int w = ClientSize.Width;
            int[] rw = GetRowHeights();

            tlpRows.Clear();
            for (int i = 0; i < rw.Length - 1; i++)
            {
                y += rw[i];
                tlpRows.Add(new RectangleF(0, y - sz, w, size));
            }

        }

        void getColRectangles(float size)
        {   // get a list of mouse sensitive rectangles
            float sz = size / 2f;
            float x = 0f;
            int h = ClientSize.Height;
            int[] rw = GetColumnWidths();

            tlpCols.Clear();
            for (int i = 0; i < rw.Length - 1; i++)
            {
                x += rw[i];
                tlpCols.Add(new RectangleF(x - sz, 0, size, h));
            }

        }

        void sizeRow(int row, int newHeight)
        {   // change the height of one row
            if (newHeight == 0) return;
            if (sizingRow < 0) return;
            SuspendLayout();
            rowHeights = GetRowHeights();
            if (sizingRow >= rowHeights.Length) return;

            if (newHeight > 0) 
                RowStyles[sizingRow] = new RowStyle(SizeType.Absolute, newHeight);
            ResumeLayout();
            rowHeights = GetRowHeights();
            getRowRectangles(SplitterSize);
        }

        void sizeCol(int col, int newWidth)
        {   // change the height of one row
            if (newWidth == 0) return;
            if (sizingCol < 0) return;
            SuspendLayout();
            colWidths = GetColumnWidths();
            if (sizingCol >= colWidths.Length) return;

            if (newWidth > 0) 
                ColumnStyles[sizingCol] = new ColumnStyle(SizeType.Absolute, newWidth);
            ResumeLayout();
            colWidths = GetColumnWidths();
            getColRectangles(SplitterSize);
        }

        void nomalizeRowStyles()
        {   // set all rows to absolute and the last one to percent=100!
            if (rowHeights.Length <= 0) return;
            rowHeights = GetRowHeights();
            RowStyles.Clear();
            for (int i = 0; i < RowCount - 1; i++)
            {
                RowStyle cs = new RowStyle(SizeType.Absolute, rowHeights[i]);
                RowStyles.Add(cs);
            }
            RowStyles.Add ( new RowStyle(SizeType.Percent, 100) );
            isNormalRow = true;
        }

        void nomalizeColStyles()
        {   // set all rows to absolute and the last one to percent=100!
            if (colWidths.Length <= 0) return;
            colWidths = GetColumnWidths();
            ColumnStyles.Clear();
            for (int i = 0; i < ColumnCount - 1; i++)
            {
                ColumnStyle cs = new ColumnStyle(SizeType.Absolute, colWidths[i]);
                ColumnStyles.Add(cs);
            }
            ColumnStyles.Add ( new ColumnStyle(SizeType.Percent, 100) );
            isNormalCol = true;
        }
    }
}

答案 2 :(得分:1)

我无法对 steve-e 的最新帖子发表评论,因为我是新用户,但是当我尝试他的控件版本时确实发现了一个错误。如果您使用鼠标滚轮,所有分离器都将停止工作。如果您滚动回顶部,它们又可以了。这是因为每当您使用鼠标滚轮向下滚动面板时,tlpRows 中每条记录的 RectangeF Y 参数都会计算错误,因此需要通过滚动移动的距离来偏移。 为此,我为 MouseWheel 和 Scroll 事件添加了一个事件,该事件将调用 getRowRectangles 并传入一个新参数来保存偏移量 (AutoScrollPosition.Y)。 在 getRowRectangles 方法中,我在创建 tlpRows 列表时将偏移量添加到 Y 参数。

tlpRows.Add(new RectangleF(0, y - sz + offset, w, size));