获得了包含1列和N行的TableLayoutPanel 细胞需要像细胞之间的分裂器组件一样可以调整大小。 不使用SplitContainer。
没有TableLayoutPanel可能是其他想法吗?
答案 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));